Commit 6adc8bc231ef3c5692621c8bec01ea6411c83f03

Authored by Rodrigo Souto
2 parents 46f13390 c9eccb09

Merge branch 'master' into rails3

Conflicts:
	app/controllers/my_profile/memberships_controller.rb
	app/helpers/application_helper.rb
	app/helpers/boxes_helper.rb
	app/models/article.rb
	app/models/category.rb
	app/models/change_password.rb
	app/models/comment.rb
	app/models/environment.rb
	app/models/event.rb
	app/models/profile.rb
	app/models/recent_documents_block.rb
	app/models/region.rb
	app/models/task.rb
	app/models/uploaded_file.rb
	app/views/account/forgot_password.html.erb
	app/views/events/_events_by_day.html.erb
	app/views/profile/_person_profile.html.erb
	app/views/shared/_manage_enterprises.html.erb
	config/environment.rb
	config/initializers/plugins.rb
	config/routes.rb
	db/schema.rb
	debian/control
	lib/noosfero/plugin.rb
	test/unit/article_test.rb
	test/unit/category_test.rb
	test/unit/change_password_test.rb
	test/unit/cms_helper_test.rb
	test/unit/comment_test.rb
	test/unit/content_viewer_helper_test.rb
	test/unit/event_test.rb
	test/unit/folder_helper_test.rb
	test/unit/person_test.rb
	test/unit/price_detail_test.rb
	test/unit/profile_helper_test.rb
	test/unit/recent_documents_block_test.rb
	test/unit/scrap_test.rb
	test/unit/user_mailer_test.rb
	vendor/plugins/action_tracker_has_comments/init.rb
	vendor/plugins/delayed_job/lib/delayed/worker.rb
	vendor/plugins/noosfero_caching/init.rb
Showing 566 changed files with 74620 additions and 59234 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 566 files displayed.

@@ -44,6 +44,7 @@ Antonio Terceiro <terceiro@colivre.coop.br> @@ -44,6 +44,7 @@ Antonio Terceiro <terceiro@colivre.coop.br>
44 Aurelio A. Heckert <aurelio@colivre.coop.br> 44 Aurelio A. Heckert <aurelio@colivre.coop.br>
45 Braulio Bhavamitra <brauliobo@gmail.com> 45 Braulio Bhavamitra <brauliobo@gmail.com>
46 Bráulio Bhavamitra <brauliobo@gmail.com> 46 Bráulio Bhavamitra <brauliobo@gmail.com>
  47 +Braulio Bhavamitra <braulio@eita.org.br>
47 Caio <caio.csalgado@gmail.com> 48 Caio <caio.csalgado@gmail.com>
48 Caio + Diego + Pedro + João <caio.csalgado@gmail.com> 49 Caio + Diego + Pedro + João <caio.csalgado@gmail.com>
49 Caio Formiga <caio.formiga@gmail.com> 50 Caio Formiga <caio.formiga@gmail.com>
@@ -110,6 +111,7 @@ Diego Martinez &lt;diegoamc90@gmail.com&gt; @@ -110,6 +111,7 @@ Diego Martinez &lt;diegoamc90@gmail.com&gt;
110 Diego Martinez <diego@diego-K55A.(none)> 111 Diego Martinez <diego@diego-K55A.(none)>
111 Diego + Renan <renanteruoc@gmail.com> 112 Diego + Renan <renanteruoc@gmail.com>
112 Fernanda Lopes <nanda.listas+psl@gmail.com> 113 Fernanda Lopes <nanda.listas+psl@gmail.com>
  114 +Francisco Marcelo A. Lima Júnior <francisco.lima-junior@serpro.gov.br>
113 Francisco Marcelo de Araujo Lima Junior <79350259591@serpro-1457614.(none)> 115 Francisco Marcelo de Araujo Lima Junior <79350259591@serpro-1457614.(none)>
114 Grazieno Pellegrino <grazieno@gmail.com> 116 Grazieno Pellegrino <grazieno@gmail.com>
115 Isaac Canan <isaac@intelletto.com.br> 117 Isaac Canan <isaac@intelletto.com.br>
@@ -147,6 +149,8 @@ João M. M. Silva + Rafael Manzo &lt;jaodsilv@linux.ime.usp.br&gt; @@ -147,6 +149,8 @@ João M. M. Silva + Rafael Manzo &lt;jaodsilv@linux.ime.usp.br&gt;
147 João M. M. Silva + Renan Teruo <jaodsilv@linux.ime.usp.br> 149 João M. M. Silva + Renan Teruo <jaodsilv@linux.ime.usp.br>
148 Joenio Costa <joenio@colivre.coop.br> 150 Joenio Costa <joenio@colivre.coop.br>
149 Josef Spillner <josef.spillner@tu-dresden.de> 151 Josef Spillner <josef.spillner@tu-dresden.de>
  152 +Junior Silva <juniorsilva1001@gmail.com>
  153 +Junior Silva <juniorsilva7@juniorsilva-Aspire-5750Z.(none)>
150 Keilla Menezes <keilla@colivre.coop.br> 154 Keilla Menezes <keilla@colivre.coop.br>
151 Larissa Reis <larissa@colivre.coop.br> 155 Larissa Reis <larissa@colivre.coop.br>
152 Larissa Reis <reiss.larissa@gmail.com> 156 Larissa Reis <reiss.larissa@gmail.com>
@@ -158,6 +162,7 @@ Lucas Melo &lt;lucaspradomelo@gmail.com&gt; @@ -158,6 +162,7 @@ Lucas Melo &lt;lucaspradomelo@gmail.com&gt;
158 Luis David Aguilar Carlos <ludwig9003@gmail.com> 162 Luis David Aguilar Carlos <ludwig9003@gmail.com>
159 Martín Olivera <molivera@solar.org.ar> 163 Martín Olivera <molivera@solar.org.ar>
160 Moises Machado <moises@colivre.coop.br> 164 Moises Machado <moises@colivre.coop.br>
  165 +Naíla Alves <naila@colivre.coop.br>
161 Nanda Lopes <nanda.listas+psl@gmail.com> 166 Nanda Lopes <nanda.listas+psl@gmail.com>
162 Paulo Meirelles + Alessandro Palmeira + João M. M. da Silva <paulo@softwarelivre.org> 167 Paulo Meirelles + Alessandro Palmeira + João M. M. da Silva <paulo@softwarelivre.org>
163 Paulo Meirelles + Alessandro Palmeira <paulo@softwarelivre.org> 168 Paulo Meirelles + Alessandro Palmeira <paulo@softwarelivre.org>
@@ -187,12 +192,15 @@ Renan Teruo + Diego Araujo &lt;renanteruoc@gmail.com&gt; @@ -187,12 +192,15 @@ Renan Teruo + Diego Araujo &lt;renanteruoc@gmail.com&gt;
187 Renan Teruo + Diego Araújo <renanteruoc@gmail.com> 192 Renan Teruo + Diego Araújo <renanteruoc@gmail.com>
188 Renan Teruo + Paulo Meirelles <renanteruoc@gmail.com> 193 Renan Teruo + Paulo Meirelles <renanteruoc@gmail.com>
189 Renan Teruo + Rafael Manzo <renanteruoc@gmail.com> 194 Renan Teruo + Rafael Manzo <renanteruoc@gmail.com>
  195 +Rodrigo Souto <diguliu@gmail.com>
190 Rodrigo Souto <rodrigo@colivre.coop.br> 196 Rodrigo Souto <rodrigo@colivre.coop.br>
191 Ronny Kursawe <kursawe.ronny@googlemail.com> 197 Ronny Kursawe <kursawe.ronny@googlemail.com>
192 root <root@debian.sdr.serpro> 198 root <root@debian.sdr.serpro>
193 Samuel R. C. Vale <srcvale@holoscopio.com> 199 Samuel R. C. Vale <srcvale@holoscopio.com>
194 Valessio Brito <valessio@gmail.com> 200 Valessio Brito <valessio@gmail.com>
195 vfcosta <vfcosta@gmail.com> 201 vfcosta <vfcosta@gmail.com>
  202 +Victor Costa <vfcosta@gmail.com>
  203 +Vinicius Cubas Brand <viniciuscb@gmail.com>
196 Visita <visita@debian.(none)> 204 Visita <visita@debian.(none)>
197 Yann Lugrin <yann.lugrin@liquid-concept.ch> 205 Yann Lugrin <yann.lugrin@liquid-concept.ch>
198 206
@@ -4,8 +4,9 @@ Copyright (c) 2007-2009, @@ -4,8 +4,9 @@ Copyright (c) 2007-2009,
4 Cáritas Brasileira <http://www.caritasbrasileira.org/> 4 Cáritas Brasileira <http://www.caritasbrasileira.org/>
5 Copyright (c) 2007-2009, 5 Copyright (c) 2007-2009,
6 Ynternet.org Foundation <http://www.ynternet.org/> 6 Ynternet.org Foundation <http://www.ynternet.org/>
7 -Copyright (c) 2008-2009, 7 +Copyright (c) 2008-2013,
8 Colivre <http://www.colivre.coop.br/> 8 Colivre <http://www.colivre.coop.br/>
  9 +Copyright (c) the Noosfero contributors. See AUTHORS
9 10
10 This program is free software: you can redistribute it and/or modify 11 This program is free software: you can redistribute it and/or modify
11 it under the terms of the GNU Affero General Public License as published by 12 it under the terms of the GNU Affero General Public License as published by
@@ -52,3 +52,12 @@ If you write such script for your own OS, *please* share it with us at the @@ -52,3 +52,12 @@ If you write such script for your own OS, *please* share it with us at the
52 development mailing list so that we can include it in the official repository. 52 development mailing list so that we can include it in the official repository.
53 This way other people using the same OS will have to put less effort to develop 53 This way other people using the same OS will have to put less effort to develop
54 Noosfero. 54 Noosfero.
  55 +
  56 +== Submitting your changes back
  57 +
  58 +For now please read:
  59 +
  60 +- Coding conventions
  61 + http://noosfero.org/Development/CodingConventions
  62 +- Patch guidelines
  63 + http://noosfero.org/Development/PatchGuidelines
HACKING.rails235
@@ -1,13 +0,0 @@ @@ -1,13 +0,0 @@
1 -This is a draft of how to create a environment to Rails 2.3.5 to Noosfero  
2 -development.  
3 -  
4 -Install dependencies:  
5 -  
6 -gem install rails -v 2.3.5  
7 -gem install i18n  
8 -gem install will_paginate -v 2.3.12  
9 -gem install cucumber  
10 -  
11 -Creating initial environment:  
12 -  
13 -rake db:schema:load  
@@ -6,7 +6,7 @@ To configure XMPP/BOSH in Noosfero you need: @@ -6,7 +6,7 @@ To configure XMPP/BOSH in Noosfero you need:
6 * SystemTimer - http://ph7spot.com/musings/system-timer 6 * SystemTimer - http://ph7spot.com/musings/system-timer
7 * Pidgin data files - http://www.pidgin.im/ 7 * Pidgin data files - http://www.pidgin.im/
8 8
9 -If you use Debian Wheezy: 9 +If you use Debian 6.0 (squeeze):
10 10
11 # apt-get install librestclient-ruby pidgin-data ruby1.8-dev 11 # apt-get install librestclient-ruby pidgin-data ruby1.8-dev
12 # gem install SystemTimer 12 # gem install SystemTimer
1 -noosfero - a web-based social platform 1 +Noosfero - a web-based social platform
2 ====================================== 2 ======================================
3 3
4 -:: About the project 4 +http://www.noosfero.org/
5 5
6 -Homepage: http://www.noosfero.org/ 6 +Documentation
  7 +-------------
7 8
8 -:: Authors and copyright 9 +The following documentation is available:
9 10
10 -Authors: see file AUTHORS  
11 -Copyright information: see file COPYRIGHT  
12 -Full license text; see file COPYING 11 +File Purpose
  12 +~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  13 +INSTALL install instructions
  14 +INSTALL.awstats install instructions - access statistics service
  15 +INSTALL.chat install instructions - chat service
  16 +INSTALL.email install instructions - email service
  17 +INSTALL.multitenancy install instructions - multiple sites
  18 +INSTALL.varnish install instructions - varnish HTTP caching (recommended)
  19 +HACKING development instruction
  20 +RELEASING instructions for doing releases
  21 +doc/noosfero/* user documentation (available through the app itself)
  22 +
  23 +
  24 +Authors and copyright
  25 +---------------------
  26 +
  27 +Authorship and copyright information is available in the files listed below.
  28 +
  29 +File Purpose
  30 +~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  31 +AUTHORS list of authors (updated at each release)
  32 +COPYRIGHT Copyright statement for the project
  33 +COPYING Full text of the project license
app/controllers/admin/features_controller.rb
@@ -2,7 +2,7 @@ class FeaturesController &lt; AdminController @@ -2,7 +2,7 @@ class FeaturesController &lt; AdminController
2 protect 'edit_environment_features', :environment 2 protect 'edit_environment_features', :environment
3 3
4 def index 4 def index
5 - @features = Environment.available_features 5 + @features = Environment.available_features.sort_by{|k,v|v}
6 end 6 end
7 7
8 post_only :update 8 post_only :update
app/controllers/admin/users_controller.rb
@@ -4,12 +4,52 @@ class UsersController &lt; AdminController @@ -4,12 +4,52 @@ class UsersController &lt; AdminController
4 4
5 protect 'manage_environment_users', :environment 5 protect 'manage_environment_users', :environment
6 6
  7 + include UsersHelper
  8 +
7 def index 9 def index
  10 + @filter = params[:filter]
  11 + scope = environment.people.no_templates
  12 + if @filter == 'admin_users'
  13 + scope = scope.admins
  14 + elsif @filter == 'activated_users'
  15 + scope = scope.activated
  16 + elsif @filter == 'deactivated_users'
  17 + scope = scope.deactivated
  18 + end
  19 + @q = params[:q]
  20 + @collection = find_by_contents(:people, scope, @q, {:per_page => per_page, :page => params[:npage]})[:results]
  21 + end
  22 +
  23 + def set_admin_role
  24 + person = environment.people.find(params[:id])
  25 + environment.add_admin(person)
  26 + redirect_to :action => :index, :q => params[:q], :filter => params[:filter]
  27 + end
  28 +
  29 + def reset_admin_role
  30 + person = environment.people.find(params[:id])
  31 + environment.remove_admin(person)
  32 + redirect_to :action => :index, :q => params[:q], :filter => params[:filter]
  33 + end
  34 +
  35 + def activate
  36 + person = environment.people.find(params[:id])
  37 + person.user.activate
  38 + redirect_to :action => :index, :q => params[:q], :filter => params[:filter]
  39 + end
  40 +
  41 + def deactivate
  42 + person = environment.people.find(params[:id])
  43 + person.user.deactivate
  44 + redirect_to :action => :index, :q => params[:q], :filter => params[:filter]
  45 + end
  46 +
  47 + def download
8 respond_to do |format| 48 respond_to do |format|
9 format.html 49 format.html
10 format.xml do 50 format.xml do
11 - @users = User.find(:all, :conditions => {:environment_id => environment.id}, :include => [:person])  
12 - send_data @users.to_xml( 51 + users = User.find(:all, :conditions => {:environment_id => environment.id}, :include => [:person])
  52 + send_data users.to_xml(
13 :skip_types => true, 53 :skip_types => true,
14 :only => %w[email login created_at updated_at], 54 :only => %w[email login created_at updated_at],
15 :include => { :person => {:only => %w[name updated_at created_at address birth_date contact_phone identifier lat lng] } }), 55 :include => { :person => {:only => %w[name updated_at created_at address birth_date contact_phone identifier lat lng] } }),
@@ -45,4 +85,10 @@ class UsersController &lt; AdminController @@ -45,4 +85,10 @@ class UsersController &lt; AdminController
45 end 85 end
46 end 86 end
47 87
  88 + private
  89 +
  90 + def per_page
  91 + 10
  92 + end
  93 +
48 end 94 end
app/controllers/application_controller.rb
@@ -5,7 +5,7 @@ class ApplicationController &lt; ActionController::Base @@ -5,7 +5,7 @@ class ApplicationController &lt; ActionController::Base
5 5
6 before_filter :setup_multitenancy 6 before_filter :setup_multitenancy
7 before_filter :detect_stuff_by_domain 7 before_filter :detect_stuff_by_domain
8 - before_filter :init_noosfero_plugins 8 + before_filter :init_noosfero_plugins_controller_filters
9 before_filter :allow_cross_domain_access 9 before_filter :allow_cross_domain_access
10 10
11 def allow_cross_domain_access 11 def allow_cross_domain_access
@@ -24,8 +24,12 @@ class ApplicationController &lt; ActionController::Base @@ -24,8 +24,12 @@ class ApplicationController &lt; ActionController::Base
24 include ApplicationHelper 24 include ApplicationHelper
25 layout :get_layout 25 layout :get_layout
26 def get_layout 26 def get_layout
27 - prepend_view_path('public/' + theme_path)  
28 - theme_option(:layout) || 'application' 27 + theme_layout = theme_option(:layout)
  28 + if theme_layout
  29 + theme_view_file('layouts/'+theme_layout) || theme_layout
  30 + else
  31 + 'application'
  32 + end
29 end 33 end
30 34
31 def log_processing 35 def log_processing
@@ -128,22 +132,21 @@ class ApplicationController &lt; ActionController::Base @@ -128,22 +132,21 @@ class ApplicationController &lt; ActionController::Base
128 132
129 include Noosfero::Plugin::HotSpot 133 include Noosfero::Plugin::HotSpot
130 134
131 - def init_noosfero_plugins  
132 - plugins.each do |plugin|  
133 - prepend_view_path(plugin.class.view_path)  
134 - end  
135 - init_noosfero_plugins_controller_filters  
136 - end  
137 -  
138 # This is a generic method that initialize any possible filter defined by a 135 # This is a generic method that initialize any possible filter defined by a
139 # plugin to the current controller being initialized. 136 # plugin to the current controller being initialized.
140 def init_noosfero_plugins_controller_filters 137 def init_noosfero_plugins_controller_filters
141 plugins.each do |plugin| 138 plugins.each do |plugin|
142 filters = plugin.send(self.class.name.underscore + '_filters') 139 filters = plugin.send(self.class.name.underscore + '_filters')
143 filters = [filters] if !filters.kind_of?(Array) 140 filters = [filters] if !filters.kind_of?(Array)
  141 + controller_filters = self.class.filter_chain.map {|c| c.method }
144 filters.each do |plugin_filter| 142 filters.each do |plugin_filter|
145 - self.class.send(plugin_filter[:type], plugin.class.name.underscore + '_' + plugin_filter[:method_name], (plugin_filter[:options] || {}))  
146 - self.class.send(:define_method, plugin.class.name.underscore + '_' + plugin_filter[:method_name], plugin_filter[:block]) 143 + filter_method = plugin.class.name.underscore.gsub('/','_') + '_' + plugin_filter[:method_name]
  144 + unless controller_filters.include?(filter_method)
  145 + self.class.send(plugin_filter[:type], filter_method, (plugin_filter[:options] || {}))
  146 + self.class.send(:define_method, filter_method) do
  147 + instance_eval(&plugin_filter[:block]) if environment.plugin_enabled?(plugin.class)
  148 + end
  149 + end
147 end 150 end
148 end 151 end
149 end 152 end
@@ -173,17 +176,16 @@ class ApplicationController &lt; ActionController::Base @@ -173,17 +176,16 @@ class ApplicationController &lt; ActionController::Base
173 end 176 end
174 177
175 def find_by_contents(asset, scope, query, paginate_options={:page => 1}, options={}) 178 def find_by_contents(asset, scope, query, paginate_options={:page => 1}, options={})
176 - scope = scope.send(options[:filter]) if options[:filter]  
177 -  
178 - @plugins.dispatch_first(:find_by_contents, asset, scope, query, paginate_options, options) || 179 + plugins.dispatch_first(:find_by_contents, asset, scope, query, paginate_options, options) ||
179 fallback_find_by_contents(asset, scope, query, paginate_options, options) 180 fallback_find_by_contents(asset, scope, query, paginate_options, options)
180 end 181 end
181 182
182 private 183 private
183 184
184 def fallback_find_by_contents(asset, scope, query, paginate_options, options) 185 def fallback_find_by_contents(asset, scope, query, paginate_options, options)
185 - return {:results => scope.paginate(paginate_options)} if query.blank?  
186 - {:results => scope.like_search(query).paginate(paginate_options)} 186 + scope = scope.like_search(query) unless query.blank?
  187 + scope = scope.send(options[:filter]) unless options[:filter].blank?
  188 + {:results => scope.paginate(paginate_options)}
187 end 189 end
188 190
189 end 191 end
app/controllers/my_profile/cms_controller.rb
@@ -73,6 +73,7 @@ class CmsController &lt; MyProfileController @@ -73,6 +73,7 @@ class CmsController &lt; MyProfileController
73 refuse_blocks 73 refuse_blocks
74 record_coming 74 record_coming
75 if request.post? 75 if request.post?
  76 + @article.image = nil if params[:remove_image] == 'true'
76 @article.last_changed_by = user 77 @article.last_changed_by = user
77 if @article.update_attributes(params[:article]) 78 if @article.update_attributes(params[:article])
78 if !continue 79 if !continue
@@ -144,10 +145,15 @@ class CmsController &lt; MyProfileController @@ -144,10 +145,15 @@ class CmsController &lt; MyProfileController
144 145
145 post_only :set_home_page 146 post_only :set_home_page
146 def set_home_page 147 def set_home_page
147 - @article = profile.articles.find(params[:id])  
148 - profile.home_page = @article  
149 - profile.save(false)  
150 - session[:notice] = _('"%s" configured as home page.') % @article.name 148 + article = params[:id].nil? ? nil : profile.articles.find(params[:id])
  149 + profile.update_attribute(:home_page, article)
  150 +
  151 + if article.nil?
  152 + session[:notice] = _('Homepage reseted.')
  153 + else
  154 + session[:notice] = _('"%s" configured as homepage.') % article.name
  155 + end
  156 +
151 redirect_to (request.referer || profile.url) 157 redirect_to (request.referer || profile.url)
152 end 158 end
153 159
@@ -267,7 +273,10 @@ class CmsController &lt; MyProfileController @@ -267,7 +273,10 @@ class CmsController &lt; MyProfileController
267 @back_to = params[:back_to] || request.referer || url_for(profile.public_profile_url) 273 @back_to = params[:back_to] || request.referer || url_for(profile.public_profile_url)
268 @task = SuggestArticle.new(params[:task]) 274 @task = SuggestArticle.new(params[:task])
269 if request.post? 275 if request.post?
270 - @task.target = profile 276 + @task.target = profile
  277 + @task.ip_address = request.remote_ip
  278 + @task.user_agent = request.user_agent
  279 + @task.referrer = request.referrer
271 if verify_recaptcha(:model => @task, :message => _('Please type the words correctly')) && @task.save 280 if verify_recaptcha(:model => @task, :message => _('Please type the words correctly')) && @task.save
272 session[:notice] = _('Thanks for your suggestion. The community administrators were notified.') 281 session[:notice] = _('Thanks for your suggestion. The community administrators were notified.')
273 redirect_to @back_to 282 redirect_to @back_to
app/controllers/my_profile/manage_products_controller.rb
@@ -6,10 +6,10 @@ class ManageProductsController &lt; ApplicationController @@ -6,10 +6,10 @@ class ManageProductsController &lt; ApplicationController
6 before_filter :login_required, :except => [:show] 6 before_filter :login_required, :except => [:show]
7 before_filter :create_product?, :only => [:new] 7 before_filter :create_product?, :only => [:new]
8 8
9 - protected 9 + protected
10 10
11 def check_environment_feature 11 def check_environment_feature
12 - if profile.environment.enabled?('disable_products_for_enterprises') 12 + unless profile.environment.enabled?('products_for_enterprises')
13 render_not_found 13 render_not_found
14 return 14 return
15 end 15 end
app/controllers/my_profile/memberships_controller.rb
1 class MembershipsController < MyProfileController 1 class MembershipsController < MyProfileController
2 2
3 protect 'manage_memberships', :profile 3 protect 'manage_memberships', :profile
4 - 4 +
5 def index 5 def index
6 - @memberships = profile.memberships 6 + @roles = environment.roles.select do |role|
  7 + ra = profile.role_assignments.find_by_role_id(role.id)
  8 + ra.present? && ra.resource_type == 'Profile'
  9 + end
  10 + @filter = params[:filter_type].blank? ? nil : params[:filter_type]
  11 + begin
  12 + @memberships = @filter.nil? ? profile.memberships : profile.memberships_by_role(environment.roles.find(@filter))
  13 + rescue ActiveRecord::RecordNotFound
  14 + @memberships = []
  15 + end
7 end 16 end
8 17
9 def new_community 18 def new_community
10 @community = Community.new(params[:community]) 19 @community = Community.new(params[:community])
11 @community.environment = environment 20 @community.environment = environment
  21 + @back_to = params[:back_to] || url_for(:action => 'index')
12 if request.post? && @community.valid? 22 if request.post? && @community.valid?
13 @community = Community.create_after_moderation(user, params[:community].merge({:environment => environment})) 23 @community = Community.create_after_moderation(user, params[:community].merge({:environment => environment}))
14 - redirect_to :action => 'index' 24 + redirect_to @back_to
15 return 25 return
16 end 26 end
17 end 27 end
app/controllers/my_profile/profile_design_controller.rb
@@ -38,7 +38,7 @@ class ProfileDesignController &lt; BoxOrganizerController @@ -38,7 +38,7 @@ class ProfileDesignController &lt; BoxOrganizerController
38 end 38 end
39 39
40 # product block exclusive for enterprises in environments that permits it 40 # product block exclusive for enterprises in environments that permits it
41 - if profile.enterprise? && !profile.environment.enabled?('disable_products_for_enterprises') 41 + if profile.enterprise? && profile.environment.enabled?('products_for_enterprises')
42 blocks << ProductsBlock 42 blocks << ProductsBlock
43 end 43 end
44 44
app/controllers/my_profile/profile_editor_controller.rb
@@ -4,7 +4,7 @@ class ProfileEditorController &lt; MyProfileController @@ -4,7 +4,7 @@ class ProfileEditorController &lt; MyProfileController
4 protect 'destroy_profile', :profile, :only => [:destroy_profile] 4 protect 'destroy_profile', :profile, :only => [:destroy_profile]
5 5
6 def index 6 def index
7 - @pending_tasks = Task.to(profile).pending.select{|i| user.has_permission?(i.permission, profile)} 7 + @pending_tasks = Task.to(profile).pending.without_spam.select{|i| user.has_permission?(i.permission, profile)}
8 end 8 end
9 9
10 helper :profile 10 helper :profile
app/controllers/my_profile/spam_controller.rb
@@ -14,9 +14,15 @@ class SpamController &lt; MyProfileController @@ -14,9 +14,15 @@ class SpamController &lt; MyProfileController
14 if params[:remove_comment] 14 if params[:remove_comment]
15 profile.comments_received.find(params[:remove_comment]).destroy 15 profile.comments_received.find(params[:remove_comment]).destroy
16 end 16 end
  17 + if params[:remove_task]
  18 + Task.to(profile).find_by_id(params[:remove_task]).destroy
  19 + end
17 if params[:mark_comment_as_ham] 20 if params[:mark_comment_as_ham]
18 profile.comments_received.find(params[:mark_comment_as_ham]).ham! 21 profile.comments_received.find(params[:mark_comment_as_ham]).ham!
19 end 22 end
  23 + if params[:mark_task_as_ham] && (t = Task.to(profile).find_by_id(params[:mark_task_as_ham]))
  24 + t.ham!
  25 + end
20 if request.xhr? 26 if request.xhr?
21 json_response(true) 27 json_response(true)
22 else 28 else
@@ -28,7 +34,8 @@ class SpamController &lt; MyProfileController @@ -28,7 +34,8 @@ class SpamController &lt; MyProfileController
28 return 34 return
29 end 35 end
30 36
31 - @spam = profile.comments_received.spam.paginate({:page => params[:page]}) 37 + @comment_spam = profile.comments_received.spam.paginate({:page => params[:comments_page]})
  38 + @task_spam = Task.to(profile).spam.paginate({:page => params[:tasks_page]})
32 end 39 end
33 40
34 protected 41 protected
app/controllers/my_profile/tasks_controller.rb
@@ -4,12 +4,12 @@ class TasksController &lt; MyProfileController @@ -4,12 +4,12 @@ class TasksController &lt; MyProfileController
4 4
5 def index 5 def index
6 @filter = params[:filter_type].blank? ? nil : params[:filter_type] 6 @filter = params[:filter_type].blank? ? nil : params[:filter_type]
7 - @tasks = Task.to(profile).pending.of(@filter).order_by('created_at', 'asc').paginate(:per_page => Task.per_page, :page => params[:page]) 7 + @tasks = Task.to(profile).without_spam.pending.of(@filter).order_by('created_at', 'asc').paginate(:per_page => Task.per_page, :page => params[:page])
8 @failed = params ? params[:failed] : {} 8 @failed = params ? params[:failed] : {}
9 end 9 end
10 10
11 def processed 11 def processed
12 - @tasks = Task.to(profile).closed.sort_by(&:created_at) 12 + @tasks = Task.to(profile).without_spam.closed.sort_by(&:created_at)
13 end 13 end
14 14
15 VALID_DECISIONS = [ 'finish', 'cancel', 'skip' ] 15 VALID_DECISIONS = [ 'finish', 'cancel', 'skip' ]
@@ -57,7 +57,7 @@ class TasksController &lt; MyProfileController @@ -57,7 +57,7 @@ class TasksController &lt; MyProfileController
57 end 57 end
58 58
59 def list_requested 59 def list_requested
60 - @tasks = Task.find_all_by_requestor_id(profile.id) 60 + @tasks = Task.without_spam.find_all_by_requestor_id(profile.id)
61 end 61 end
62 62
63 def ticket_details 63 def ticket_details
app/controllers/public/account_controller.rb
@@ -141,22 +141,34 @@ class AccountController &lt; ApplicationController @@ -141,22 +141,34 @@ class AccountController &lt; ApplicationController
141 end 141 end
142 end 142 end
143 143
144 - # The user requests a password change. She forgot her old password.  
145 - #  
146 - # Posts back. 144 + include ForgotPasswordHelper
  145 + helper :forgot_password
  146 +
147 def forgot_password 147 def forgot_password
148 if @plugins.dispatch(:allow_password_recovery).include?(false) 148 if @plugins.dispatch(:allow_password_recovery).include?(false)
149 redirect_back_or_default(:controller => 'home') 149 redirect_back_or_default(:controller => 'home')
150 session[:notice] = _("This environment doesn't allow password recovery.") 150 session[:notice] = _("This environment doesn't allow password recovery.")
151 end 151 end
152 - @change_password = ChangePassword.new(params[:change_password]) 152 +
  153 + @change_password = ChangePassword.new
153 154
154 if request.post? 155 if request.post?
155 begin 156 begin
156 - @change_password.save! 157 + requestors = fetch_requestors(params[:value])
  158 + raise ActiveRecord::RecordNotFound if requestors.blank? || params[:value].blank?
  159 +
  160 + requestors.each do |requestor|
  161 + ChangePassword.create!(:requestor => requestor)
  162 + end
157 render :action => 'password_recovery_sent' 163 render :action => 'password_recovery_sent'
158 - rescue ActiveRecord::RecordInvalid => e  
159 - nil # just pass and render at the end of the action 164 + rescue ActiveRecord::RecordNotFound
  165 + if params[:value].blank?
  166 + @change_password.errors.add_to_base(_('Can not recover user password with blank value.'))
  167 + else
  168 + @change_password.errors.add_to_base(_('Could not find any user with %s equal to "%s".') % [fields_label, params[:value]])
  169 + end
  170 + rescue ActiveRecord::RecordInvald
  171 + @change_password.errors.add_to_base(_('Could not perform password recovery for the user.'))
160 end 172 end
161 end 173 end
162 end 174 end
@@ -262,7 +274,7 @@ class AccountController &lt; ApplicationController @@ -262,7 +274,7 @@ class AccountController &lt; ApplicationController
262 def user_data 274 def user_data
263 user_data = 275 user_data =
264 if logged_in? 276 if logged_in?
265 - current_user.data_hash 277 + current_user.data_hash(gravatar_default)
266 else 278 else
267 { } 279 { }
268 end 280 end
app/controllers/public/catalog_controller.rb
@@ -12,7 +12,7 @@ class CatalogController &lt; PublicController @@ -12,7 +12,7 @@ class CatalogController &lt; PublicController
12 protected 12 protected
13 13
14 def check_enterprise_and_environment 14 def check_enterprise_and_environment
15 - unless profile.kind_of?(Enterprise) && !profile.environment.enabled?('disable_products_for_enterprises') 15 + unless profile.kind_of?(Enterprise) && @profile.environment.enabled?('products_for_enterprises')
16 redirect_to :controller => 'profile', :profile => profile.identifier, :action => 'index' 16 redirect_to :controller => 'profile', :profile => profile.identifier, :action => 'index'
17 end 17 end
18 end 18 end
app/controllers/public/content_viewer_controller.rb
@@ -53,8 +53,11 @@ class ContentViewerController &lt; ApplicationController @@ -53,8 +53,11 @@ class ContentViewerController &lt; ApplicationController
53 # At this point the page will be showed 53 # At this point the page will be showed
54 @page.hit 54 @page.hit
55 55
56 - unless @page.mime_type == 'text/html' || (@page.image? && params[:view]) 56 + @page = FilePresenter.for @page
  57 +
  58 + if @page.download? params[:view]
57 headers['Content-Type'] = @page.mime_type 59 headers['Content-Type'] = @page.mime_type
  60 + headers.merge! @page.download_headers
58 data = @page.data 61 data = @page.data
59 62
60 # TODO test the condition 63 # TODO test the condition
@@ -70,7 +73,7 @@ class ContentViewerController &lt; ApplicationController @@ -70,7 +73,7 @@ class ContentViewerController &lt; ApplicationController
70 73
71 #FIXME see a better way to do this. It's not need to pass this variable anymore 74 #FIXME see a better way to do this. It's not need to pass this variable anymore
72 @comment = Comment.new 75 @comment = Comment.new
73 - 76 +
74 if @page.has_posts? 77 if @page.has_posts?
75 posts = if params[:year] and params[:month] 78 posts = if params[:year] and params[:month]
76 filter_date = DateTime.parse("#{params[:year]}-#{params[:month]}-01") 79 filter_date = DateTime.parse("#{params[:year]}-#{params[:month]}-01")
@@ -79,15 +82,21 @@ class ContentViewerController &lt; ApplicationController @@ -79,15 +82,21 @@ class ContentViewerController &lt; ApplicationController
79 @page.posts 82 @page.posts
80 end 83 end
81 84
82 - if @page.blog? && @page.display_posts_in_current_language?  
83 - posts = posts.native_translations.all(Article.display_filter(user, profile)).map{ |p| p.get_translation_to(FastGettext.locale) }.compact  
84 - end 85 + #FIXME Need to run this before the pagination because this version of
  86 + # will_paginate returns a will_paginate collection instead of a
  87 + # relation.
  88 + blog_with_translation = @page.blog? && @page.display_posts_in_current_language?
  89 + posts = posts.native_translations if blog_with_translation
85 90
86 @posts = posts.paginate({ :page => params[:npage], :per_page => @page.posts_per_page }.merge(Article.display_filter(user, profile))) 91 @posts = posts.paginate({ :page => params[:npage], :per_page => @page.posts_per_page }.merge(Article.display_filter(user, profile)))
  92 +
  93 + if blog_with_translation
  94 + @posts.replace @posts.map{ |p| p.get_translation_to(FastGettext.locale) }.compact
  95 + end
87 end 96 end
88 97
89 if @page.folder? && @page.gallery? 98 if @page.folder? && @page.gallery?
90 - @images = @page.images 99 + @images = @page.images.select{ |a| a.display_to? user }
91 @images = @images.paginate(:per_page => per_page, :page => params[:npage]) unless params[:slideshow] 100 @images = @images.paginate(:per_page => per_page, :page => params[:npage]) unless params[:slideshow]
92 end 101 end
93 102
@@ -100,9 +109,9 @@ class ContentViewerController &lt; ApplicationController @@ -100,9 +109,9 @@ class ContentViewerController &lt; ApplicationController
100 end 109 end
101 110
102 @comments = @page.comments.without_spam 111 @comments = @page.comments.without_spam
  112 + @comments = @plugins.filter(:unavailable_comments, @comments)
103 @comments_count = @comments.count 113 @comments_count = @comments.count
104 - @comments = @plugins.filter(:unavailable_comments, @comments.without_reply)  
105 - @comments = @comments.paginate(:per_page => per_page, :page => params[:comment_page] ) 114 + @comments = @comments.without_reply.paginate(:per_page => per_page, :page => params[:comment_page] )
106 115
107 if params[:slideshow] 116 if params[:slideshow]
108 render :action => 'slideshow', :layout => 'slideshow' 117 render :action => 'slideshow', :layout => 'slideshow'
app/controllers/public/events_controller.rb
1 class EventsController < PublicController 1 class EventsController < PublicController
2 2
3 needs_profile 3 needs_profile
4 - no_design_blocks  
5 4
6 def events 5 def events
7 - @selected_day = nil  
8 - @events_of_the_day = []  
9 - date = build_date(params[:year], params[:month], params[:day]) 6 + @events = []
  7 + @date = build_date(params[:year], params[:month], params[:day])
10 8
11 - if params[:day] || !params[:year] && !params[:month]  
12 - @selected_day = date  
13 - @events_of_the_day = profile.events.by_day(@selected_day) 9 + if !params[:year] && !params[:month] && !params[:day]
  10 + @events = profile.events.next_events_from_month(@date)
14 end 11 end
15 12
16 - events = profile.events.by_range((date - 1.month).at_beginning_of_month..(date + 1.month).at_end_of_month) 13 + if params[:year] || params[:month]
  14 + @events = profile.events.by_month(@date)
  15 + end
  16 +
  17 + events_in_range = profile.events.by_range((@date - 1.month).at_beginning_of_month .. (@date + 1.month).at_end_of_month)
17 18
18 - @calendar = populate_calendar(date, events)  
19 - @previous_calendar = populate_calendar(date - 1.month, events)  
20 - @next_calendar = populate_calendar(date + 1.month, events) 19 + @calendar = populate_calendar(@date, events_in_range)
21 end 20 end
22 21
23 def events_by_day 22 def events_by_day
24 - @selected_day = build_date(params[:year], params[:month], params[:day])  
25 - @events_of_the_day = profile.events.by_day(@selected_day)  
26 - render :partial => 'events_by_day' 23 + @date = build_date(params[:year], params[:month], params[:day])
  24 + @events = profile.events.by_day(@date)
  25 + render :partial => 'events'
27 end 26 end
28 27
29 protected 28 protected
app/controllers/public/profile_controller.rb
@@ -206,10 +206,50 @@ class ProfileController &lt; PublicController @@ -206,10 +206,50 @@ class ProfileController &lt; PublicController
206 end 206 end
207 207
208 def view_more_network_activities 208 def view_more_network_activities
209 - @activities = @profile.tracked_notifications.paginate(:per_page => 10, :page => params[:page]) 209 + @activities = @profile.tracked_notifications.paginate(:per_page => 10, :page => params[:page])
210 render :partial => 'profile_network_activities', :locals => {:network_activities => @activities} 210 render :partial => 'profile_network_activities', :locals => {:network_activities => @activities}
211 end 211 end
212 212
  213 + def more_comments
  214 + activity = ActionTracker::Record.find(:first, :conditions => {:id => params[:activity], :user_id => @profile})
  215 + comments_count = activity.comments.count
  216 + comment_page = (params[:comment_page] || 1).to_i
  217 + comments_per_page = 5
  218 + no_more_pages = comments_count <= comment_page * comments_per_page
  219 +
  220 + render :update do |page|
  221 + page.insert_html :bottom, 'profile-wall-activities-comments-'+params[:activity],
  222 + :partial => 'comment', :collection => activity.comments.paginate(:per_page => comments_per_page, :page => comment_page)
  223 +
  224 + if no_more_pages
  225 + page.remove 'profile-wall-activities-comments-more-'+params[:activity]
  226 + else
  227 + page.replace_html 'profile-wall-activities-comments-more-'+params[:activity],
  228 + :partial => 'more_comments', :locals => {:activity => activity, :comment_page => comment_page}
  229 + end
  230 + end
  231 + end
  232 +
  233 + def more_replies
  234 + activity = Scrap.find(:first, :conditions => {:id => params[:activity], :receiver_id => @profile, :scrap_id => nil})
  235 + comments_count = activity.replies.count
  236 + comment_page = (params[:comment_page] || 1).to_i
  237 + comments_per_page = 5
  238 + no_more_pages = comments_count <= comment_page * comments_per_page
  239 +
  240 + render :update do |page|
  241 + page.insert_html :bottom, 'profile-wall-activities-comments-'+params[:activity],
  242 + :partial => 'profile_scrap', :collection => activity.replies.paginate(:per_page => comments_per_page, :page => comment_page), :as => :scrap
  243 +
  244 + if no_more_pages
  245 + page.remove 'profile-wall-activities-comments-more-'+params[:activity]
  246 + else
  247 + page.replace_html 'profile-wall-activities-comments-more-'+params[:activity],
  248 + :partial => 'more_replies', :locals => {:activity => activity, :comment_page => comment_page}
  249 + end
  250 + end
  251 + end
  252 +
213 def remove_scrap 253 def remove_scrap
214 begin 254 begin
215 scrap = current_user.person.scraps(params[:scrap_id]) 255 scrap = current_user.person.scraps(params[:scrap_id])
@@ -343,6 +383,7 @@ class ProfileController &lt; PublicController @@ -343,6 +383,7 @@ class ProfileController &lt; PublicController
343 end 383 end
344 end 384 end
345 385
  386 +
346 protected 387 protected
347 388
348 def check_access_to_profile 389 def check_access_to_profile
@@ -393,4 +434,5 @@ class ProfileController &lt; PublicController @@ -393,4 +434,5 @@ class ProfileController &lt; PublicController
393 def relations_to_include 434 def relations_to_include
394 [:image, :domains, :preferred_domain, :environment] 435 [:image, :domains, :preferred_domain, :environment]
395 end 436 end
  437 +
396 end 438 end
app/controllers/public/search_controller.rb
@@ -93,25 +93,27 @@ class SearchController &lt; PublicController @@ -93,25 +93,27 @@ class SearchController &lt; PublicController
93 year = (params[:year] ? params[:year].to_i : Date.today.year) 93 year = (params[:year] ? params[:year].to_i : Date.today.year)
94 month = (params[:month] ? params[:month].to_i : Date.today.month) 94 month = (params[:month] ? params[:month].to_i : Date.today.month)
95 day = (params[:day] ? params[:day].to_i : Date.today.day) 95 day = (params[:day] ? params[:day].to_i : Date.today.day)
96 - date = build_date(params[:year], params[:month], params[:day])  
97 - date_range = (date - 1.month).at_beginning_of_month..(date + 1.month).at_end_of_month 96 + @date = build_date(year, month, day)
  97 + date_range = (@date - 1.month).at_beginning_of_month..(@date + 1.month).at_end_of_month
98 98
99 - @selected_day = nil  
100 - @events_of_the_day = [] 99 + @events = []
101 if params[:day] || !params[:year] && !params[:month] 100 if params[:day] || !params[:year] && !params[:month]
102 - @selected_day = date  
103 - @events_of_the_day = @category ?  
104 - environment.events.by_day(@selected_day).in_category(Category.find(@category_id)) :  
105 - environment.events.by_day(@selected_day) 101 + @events = @category ?
  102 + environment.events.by_day(@date).in_category(Category.find(@category_id)) :
  103 + environment.events.by_day(@date)
  104 + end
  105 +
  106 + if params[:year] || params[:month]
  107 + @events = @category ?
  108 + environment.events.by_month(@date).in_category(Category.find(@category_id)) :
  109 + environment.events.by_month(@date)
106 end 110 end
107 111
108 @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
109 full_text_search 113 full_text_search
110 114
111 events = @searches[@asset][:results] 115 events = @searches[@asset][:results]
112 - @calendar = populate_calendar(date, events)  
113 - @previous_calendar = populate_calendar(date - 1.month, events)  
114 - @next_calendar = populate_calendar(date + 1.month, events) 116 + @calendar = populate_calendar(@date, events)
115 end 117 end
116 118
117 # keep old URLs workings 119 # keep old URLs workings
@@ -136,9 +138,9 @@ class SearchController &lt; PublicController @@ -136,9 +138,9 @@ class SearchController &lt; PublicController
136 end 138 end
137 139
138 def events_by_day 140 def events_by_day
139 - @selected_day = build_date(params[:year], params[:month], params[:day])  
140 - @events_of_the_day = environment.events.by_day(@selected_day)  
141 - render :partial => 'events/events_by_day' 141 + @date = build_date(params[:year], params[:month], params[:day])
  142 + @events = environment.events.by_day(@date)
  143 + render :partial => 'events/events'
142 end 144 end
143 145
144 ####################################################### 146 #######################################################
app/helpers/application_helper.rb
@@ -40,6 +40,8 @@ module ApplicationHelper @@ -40,6 +40,8 @@ module ApplicationHelper
40 40
41 include LayoutHelper 41 include LayoutHelper
42 42
  43 + include Noosfero::Gravatar
  44 +
43 VIEW_EXTENSIONS = ['.rhtml', '.html.erb'] 45 VIEW_EXTENSIONS = ['.rhtml', '.html.erb']
44 46
45 def locale 47 def locale
@@ -367,7 +369,7 @@ module ApplicationHelper @@ -367,7 +369,7 @@ module ApplicationHelper
367 def current_theme 369 def current_theme
368 @current_theme ||= 370 @current_theme ||=
369 begin 371 begin
370 - if (session[:theme]) 372 + if session[:theme]
371 session[:theme] 373 session[:theme]
372 else 374 else
373 # utility for developers: set the theme to 'random' in development mode and 375 # utility for developers: set the theme to 'random' in development mode and
@@ -376,7 +378,7 @@ module ApplicationHelper @@ -376,7 +378,7 @@ module ApplicationHelper
376 if Rails.env.development? && environment.theme == 'random' 378 if Rails.env.development? && environment.theme == 'random'
377 @random_theme ||= Dir.glob('public/designs/themes/*').map { |f| File.basename(f) }.rand 379 @random_theme ||= Dir.glob('public/designs/themes/*').map { |f| File.basename(f) }.rand
378 @random_theme 380 @random_theme
379 - elsif Rails.env.development? && params[:theme] && File.exists?(Rails.root.join('public/designs/themes', params[:theme])) 381 + elsif Rails.env.development? && respond_to?(:params) && params[:theme] && File.exists?(Rails.root.join('public/designs/themes', params[:theme]))
380 params[:theme] 382 params[:theme]
381 else 383 else
382 if profile && !profile.theme.nil? 384 if profile && !profile.theme.nil?
@@ -398,18 +400,25 @@ module ApplicationHelper @@ -398,18 +400,25 @@ module ApplicationHelper
398 end 400 end
399 end 401 end
400 402
401 - def theme_include(template)  
402 - # XXX Since we cannot control what people are doing in external themes, we 403 + def theme_view_file(template)
  404 + # Since we cannot control what people are doing in external themes, we
403 # will keep looking for the deprecated .rhtml extension here. 405 # will keep looking for the deprecated .rhtml extension here.
404 VIEW_EXTENSIONS.each do |ext| 406 VIEW_EXTENSIONS.each do |ext|
405 file = Rails.root.join('public', theme_path[1..-1], template + ext) 407 file = Rails.root.join('public', theme_path[1..-1], template + ext)
406 - if File.exists?(file)  
407 - return render :file => file, :use_full_path => false  
408 - end 408 + return file if File.exists?(file)
409 end 409 end
410 nil 410 nil
411 end 411 end
412 412
  413 + def theme_include(template)
  414 + file = theme_view_file(template)
  415 + if file
  416 + render :file => file, :use_full_path => false
  417 + else
  418 + nil
  419 + end
  420 + end
  421 +
413 def theme_favicon 422 def theme_favicon
414 return '/designs/themes/' + current_theme + '/favicon.ico' if profile.nil? || profile.theme.nil? 423 return '/designs/themes/' + current_theme + '/favicon.ico' if profile.nil? || profile.theme.nil?
415 if File.exists?(Rails.root.join('public', theme_path, 'favicon.ico')) 424 if File.exists?(Rails.root.join('public', theme_path, 'favicon.ico'))
@@ -561,6 +570,9 @@ module ApplicationHelper @@ -561,6 +570,9 @@ module ApplicationHelper
561 # displays a link to the profile homepage with its image (as generated by 570 # displays a link to the profile homepage with its image (as generated by
562 # #profile_image) and its name below it. 571 # #profile_image) and its name below it.
563 def profile_image_link( profile, size=:portrait, tag='li', extra_info = nil ) 572 def profile_image_link( profile, size=:portrait, tag='li', extra_info = nil )
  573 + if content = @plugins.dispatch_first(:profile_image_link, profile, size, tag, extra_info)
  574 + return instance_eval(&content)
  575 + end
564 name = profile.short_name 576 name = profile.short_name
565 if profile.person? 577 if profile.person?
566 url = url_for(profile.check_friendship_url) 578 url = url_for(profile.check_friendship_url)
@@ -577,45 +589,20 @@ module ApplicationHelper @@ -577,45 +589,20 @@ module ApplicationHelper
577 extra_info = extra_info.nil? ? '' : content_tag( 'span', extra_info, :class => 'extra_info' ) 589 extra_info = extra_info.nil? ? '' : content_tag( 'span', extra_info, :class => 'extra_info' )
578 links = links_for_balloon(profile) 590 links = links_for_balloon(profile)
579 content_tag('div', content_tag(tag, 591 content_tag('div', content_tag(tag,
580 - (environment.enabled?(:show_balloon_with_profile_links_when_clicked) ? link_to( content_tag( 'span', _('Profile links')), '#', :onclick => "toggleSubmenu(this, '#{profile.short_name}', #{links.to_json}); return false", :class => "menu-submenu-trigger #{trigger_class}", :url => url) : "") +  
581 - link_to(  
582 - content_tag( 'span', profile_image( profile, size ), :class => 'profile-image' ) +  
583 - content_tag( 'span', h(name), :class => ( profile.class == Person ? 'fn' : 'org' ) ) +  
584 - extra_info + profile_sex_icon( profile ) + profile_cat_icons( profile ),  
585 - profile.url,  
586 - :class => 'profile_link url',  
587 - :help => _('Click on this icon to go to the <b>%s</b>\'s home page') % profile.name,  
588 - :title => profile.name ),  
589 - :class => 'vcard'), :class => 'common-profile-list-block')  
590 - end  
591 -  
592 - def gravatar_url_for(email, options = {})  
593 - # Ta dando erro de roteamento  
594 - default = theme_option['gravatar'] || NOOSFERO_CONF['gravatar'] || nil  
595 - url_for( { :gravatar_id => Digest::MD5.hexdigest(email.to_s),  
596 - :host => 'www.gravatar.com',  
597 - :protocol => 'http://',  
598 - :only_path => false,  
599 - :controller => 'avatar.php',  
600 - :d => default  
601 - }.merge(options) )  
602 - end  
603 -  
604 - def str_gravatar_url_for(email, options = {})  
605 - default = theme_option['gravatar'] || NOOSFERO_CONF['gravatar'] || nil  
606 - url = 'http://www.gravatar.com/avatar.php?gravatar_id=' +  
607 - Digest::MD5.hexdigest(email.to_s)  
608 - {  
609 - :only_path => false,  
610 - :d => default  
611 - }.merge(options).each { |k,v|  
612 - url += ( '&%s=%s' % [ k,v ] )  
613 - }  
614 - url  
615 - end  
616 -  
617 - def gravatar_profile_url(email)  
618 - 'http://www.gravatar.com/'+ Digest::MD5.hexdigest(email.to_s) 592 + (environment.enabled?(:show_balloon_with_profile_links_when_clicked) ? link_to( content_tag( 'span', _('Profile links')), '#', :onclick => "toggleSubmenu(this, '#{profile.short_name}', #{links.to_json}); return false", :class => "menu-submenu-trigger #{trigger_class}", :url => url) : "") +
  593 + link_to(
  594 + content_tag( 'span', profile_image( profile, size ), :class => 'profile-image' ) +
  595 + content_tag( 'span', h(name), :class => ( profile.class == Person ? 'fn' : 'org' ) ) +
  596 + extra_info + profile_sex_icon( profile ) + profile_cat_icons( profile ),
  597 + profile.url,
  598 + :class => 'profile_link url',
  599 + :help => _('Click on this icon to go to the <b>%s</b>\'s home page') % profile.name,
  600 + :title => profile.name ),
  601 + :class => 'vcard'), :class => 'common-profile-list-block')
  602 + end
  603 +
  604 + def gravatar_default
  605 + (respond_to?(:theme_option) && theme_option.present? && theme_option['gravatar']) || NOOSFERO_CONF['gravatar']
619 end 606 end
620 607
621 attr_reader :environment 608 attr_reader :environment
@@ -730,8 +717,15 @@ module ApplicationHelper @@ -730,8 +717,15 @@ module ApplicationHelper
730 end 717 end
731 718
732 def rolename_for(profile, resource) 719 def rolename_for(profile, resource)
733 - role = profile.role_assignments.find_by_resource_id(resource.id).role  
734 - content_tag('span', role.name, :style => "color: #{role_color(role, resource.environment.id)}") 720 + roles = profile.role_assignments.
  721 + where(:resource_id => resource.id).
  722 + sort_by{ |role_assignment| role_assignment.role_id }.
  723 + map(&:role)
  724 + names = []
  725 + roles.each do |role|
  726 + names << content_tag('span', role.name, :style => "color: #{role_color(role, resource.environment.id)}")
  727 + end
  728 + names.join(', ')
735 end 729 end
736 730
737 def role_color(role, env_id) 731 def role_color(role, env_id)
@@ -945,7 +939,7 @@ module ApplicationHelper @@ -945,7 +939,7 @@ module ApplicationHelper
945 (@category ? " - #{@category.full_name}" : '') 939 (@category ? " - #{@category.full_name}" : '')
946 end 940 end
947 941
948 - # DEPRECATED. Do not use this· 942 + # DEPRECATED. Do not use this.
949 def import_controller_stylesheets(options = {}) 943 def import_controller_stylesheets(options = {})
950 stylesheet_import( "controller_"+ controller.controller_name(), options ) 944 stylesheet_import( "controller_"+ controller.controller_name(), options )
951 end 945 end
@@ -1128,15 +1122,34 @@ module ApplicationHelper @@ -1128,15 +1122,34 @@ module ApplicationHelper
1128 result 1122 result
1129 end 1123 end
1130 1124
1131 - def manage_enterprises  
1132 - if user && !user.enterprises.empty?  
1133 - enterprises_link = user.enterprises.map do |enterprise|  
1134 - link_to(content_tag('strong', [_('<span>Manage</span> %s') % enterprise.short_name(25)]), @environment.top_url + "/myprofile/#{enterprise.identifier}", :class => "icon-menu-"+enterprise.class.identification.underscore, :title => [_('Manage %s') % enterprise.short_name]) 1125 + def manage_link(list, kind)
  1126 + if list.present?
  1127 + link_to_all = nil
  1128 + if list.count > 5
  1129 + list = list.first(5)
  1130 + link_to_all = link_to(content_tag('strong', _('See all')), :controller => 'memberships', :profile => current_user.login)
  1131 + end
  1132 + link = list.map do |element|
  1133 + link_to(content_tag('strong', [_('<span>Manage</span> %s') % element.short_name(25)]), @environment.top_url + "/myprofile/#{element.identifier}", :class => "icon-menu-"+element.class.identification.underscore, :title => [_('Manage %s') % element.short_name])
  1134 + end
  1135 + if link_to_all
  1136 + link << link_to_all
1135 end 1137 end
1136 - render :partial => 'shared/manage_enterprises', :locals => {:enterprises_link => enterprises_link} 1138 + render :partial => "shared/manage_link", :locals => {:link => link, :kind => kind.to_s}
1137 end 1139 end
1138 end 1140 end
1139 1141
  1142 + def manage_enterprises
  1143 + return unless user && user.environment.enabled?(:display_my_enterprises_on_user_menu)
  1144 + manage_link(user.enterprises, :enterprises)
  1145 + end
  1146 +
  1147 + def manage_communities
  1148 + return unless user && user.environment.enabled?(:display_my_communities_on_user_menu)
  1149 + administered_communities = user.communities.more_popular.select {|c| c.admins.include? user}
  1150 + manage_link(administered_communities, :communities)
  1151 + end
  1152 +
1140 def usermenu_logged_in 1153 def usermenu_logged_in
1141 pending_tasks_count = '' 1154 pending_tasks_count = ''
1142 count = user ? Task.to(user).pending.count : -1 1155 count = user ? Task.to(user).pending.count : -1
@@ -1144,11 +1157,12 @@ module ApplicationHelper @@ -1144,11 +1157,12 @@ module ApplicationHelper
1144 pending_tasks_count = link_to(count.to_s, @environment.top_url + '/myprofile/{login}/tasks', :id => 'pending-tasks-count', :title => _("Manage your pending tasks")) 1157 pending_tasks_count = link_to(count.to_s, @environment.top_url + '/myprofile/{login}/tasks', :id => 'pending-tasks-count', :title => _("Manage your pending tasks"))
1145 end 1158 end
1146 1159
1147 - (_("<span class='welcome'>Welcome,</span> %s") % link_to('<i></i><strong>{login}</strong>', @environment.top_url + '/{login}', :id => "homepage-link", :title => _('Go to your homepage'))) + 1160 + (_("<span class='welcome'>Welcome,</span> %s") % link_to('<i style="background-image:url({avatar})"></i><strong>{login}</strong>', @environment.top_url + '/{login}', :id => "homepage-link", :title => _('Go to your homepage'))) +
1148 render_environment_features(:usermenu) + 1161 render_environment_features(:usermenu) +
1149 - link_to('<i class="icon-menu-admin"></i><strong>' + _('Administration') + '</strong>', @environment.top_url + '/admin', :id => "controlpanel", :title => _("Configure the environment"), :class => 'admin-link', :style => 'display: none') + 1162 + link_to('<i class="icon-menu-admin"></i><strong>' + _('Administration') + '</strong>', @environment.top_url + '/admin', :title => _("Configure the environment"), :class => 'admin-link', :style => 'display: none') +
1150 manage_enterprises.to_s + 1163 manage_enterprises.to_s +
1151 - link_to('<i class="icon-menu-ctrl-panel"></i><strong>' + _('Control panel') + '</strong>', @environment.top_url + '/myprofile/{login}', :id => "controlpanel", :title => _("Configure your personal account and content")) + 1164 + manage_communities.to_s +
  1165 + link_to('<i class="icon-menu-ctrl-panel"></i><strong>' + _('Control panel') + '</strong>', @environment.top_url + '/myprofile/{login}', :class => 'ctrl-panel', :title => _("Configure your personal account and content")) +
1152 pending_tasks_count + 1166 pending_tasks_count +
1153 link_to('<i class="icon-menu-logout"></i><strong>' + _('Logout') + '</strong>', { :controller => 'account', :action => 'logout'} , :id => "logout", :title => _("Leave the system")) 1167 link_to('<i class="icon-menu-logout"></i><strong>' + _('Logout') + '</strong>', { :controller => 'account', :action => 'logout'} , :id => "logout", :title => _("Leave the system"))
1154 end 1168 end
@@ -1325,8 +1339,8 @@ module ApplicationHelper @@ -1325,8 +1339,8 @@ module ApplicationHelper
1325 @plugins.dispatch("content_remove_#{action.to_s}", @page).include?(true) 1339 @plugins.dispatch("content_remove_#{action.to_s}", @page).include?(true)
1326 end 1340 end
1327 1341
1328 - def template_options(klass, field_name)  
1329 - templates = klass.templates(environment) 1342 + def template_options(kind, field_name)
  1343 + templates = environment.send(kind).templates
1330 return '' if templates.count == 0 1344 return '' if templates.count == 0
1331 return hidden_field_tag("#{field_name}[template_id]", templates.first.id) if templates.count == 1 1345 return hidden_field_tag("#{field_name}[template_id]", templates.first.id) if templates.count == 1
1332 1346
@@ -1440,8 +1454,8 @@ module ApplicationHelper @@ -1440,8 +1454,8 @@ module ApplicationHelper
1440 end 1454 end
1441 1455
1442 def filter_html(html, source) 1456 def filter_html(html, source)
1443 - if @plugins  
1444 - html = convert_macro(html, source) 1457 + if @plugins && source && source.has_macro?
  1458 + html = convert_macro(html, source) unless @plugins.enabled_macros.blank?
1445 #TODO This parse should be done through the macro infra, but since there 1459 #TODO This parse should be done through the macro infra, but since there
1446 # are old things that do not support it we are keeping this hot spot. 1460 # are old things that do not support it we are keeping this hot spot.
1447 html = @plugins.pipeline(:parse_content, html, source).first 1461 html = @plugins.pipeline(:parse_content, html, source).first
app/helpers/blog_helper.rb
@@ -42,7 +42,7 @@ module BlogHelper @@ -42,7 +42,7 @@ module BlogHelper
42 42
43 def display_post(article, format = 'full') 43 def display_post(article, format = 'full')
44 no_comments = (format == 'full') ? false : true 44 no_comments = (format == 'full') ? false : true
45 - html = send("display_#{format}_format", article) 45 + html = send("display_#{format}_format", FilePresenter.for(article)).html_safe
46 46
47 article_title(article, :no_comments => no_comments) + html 47 article_title(article, :no_comments => no_comments) + html
48 end 48 end
app/helpers/boxes_helper.rb
@@ -99,17 +99,19 @@ module BoxesHelper @@ -99,17 +99,19 @@ module BoxesHelper
99 unless block.visible? 99 unless block.visible?
100 options[:title] = _("This block is invisible. Your visitors will not see it.") 100 options[:title] = _("This block is invisible. Your visitors will not see it.")
101 end 101 end
102 - if controller.send(:content_editor?)  
103 - result = filter_html(result, block)  
104 - end  
105 - box_decorator.block_target(block.box, block) +  
106 - content_tag('div',  
107 - content_tag('div', 102 +
  103 + result = filter_html(result, block)
  104 +
  105 + content_tag('div',
  106 + box_decorator.block_target(block.box, block) +
  107 + content_tag('div',
108 content_tag('div', 108 content_tag('div',
109 - result + footer_content + box_decorator.block_edit_buttons(block),  
110 - :class => 'block-inner-2'),  
111 - :class => 'block-inner-1'),  
112 - options) + 109 + content_tag('div',
  110 + result + footer_content + box_decorator.block_edit_buttons(block),
  111 + :class => 'block-inner-2'),
  112 + :class => 'block-inner-1'),
  113 + options),
  114 + :class => 'block-outer') +
113 box_decorator.block_handle(block) 115 box_decorator.block_handle(block)
114 end 116 end
115 117
@@ -225,15 +227,11 @@ module BoxesHelper @@ -225,15 +227,11 @@ module BoxesHelper
225 227
226 # DEPRECATED. Do not use this. 228 # DEPRECATED. Do not use this.
227 def import_blocks_stylesheets(options = {}) 229 def import_blocks_stylesheets(options = {})
228 - @blocks_css_files ||= current_blocks.map{|b|'blocks/' + block_css_class_name(b)}.uniq 230 + @blocks_css_files ||= current_blocks.map{|b|'blocks/' + block.class.name.to_css_class}.uniq
229 stylesheet_import(@blocks_css_files, options) 231 stylesheet_import(@blocks_css_files, options)
230 end 232 end
231 -  
232 - def block_css_class_name(block)  
233 - block.class.name.underscore.gsub('_', '-')  
234 - end  
235 def block_css_classes(block) 233 def block_css_classes(block)
236 - classes = block_css_class_name(block) 234 + classes = block.class.name.to_css_class
237 classes += ' invisible-block' if block.display == 'never' 235 classes += ' invisible-block' if block.display == 'never'
238 classes 236 classes
239 end 237 end
app/helpers/categories_helper.rb
@@ -3,10 +3,21 @@ module CategoriesHelper @@ -3,10 +3,21 @@ module CategoriesHelper
3 3
4 COLORS = [ 4 COLORS = [
5 [ N_('Do not display at the menu'), nil ], 5 [ N_('Do not display at the menu'), nil ],
6 - [ N_('Orange'), 1 ],  
7 - [ N_('Green'), 2 ],  
8 - [ N_('Purple'), 3 ],  
9 - [ N_('Red'), 4 ], 6 + [ N_('Orange'), 1],
  7 + [ N_('Green'), 2],
  8 + [ N_('Purple'), 3],
  9 + [ N_('Red'), 4],
  10 + [ N_('Dark Green'), 5],
  11 + [ N_('Blue Oil'), 6],
  12 + [ N_('Blue'), 7],
  13 + [ N_('Brown'), 8],
  14 + [ N_('Light Green'), 9],
  15 + [ N_('Light Blue'), 10],
  16 + [ N_('Dark Blue'), 11],
  17 + [ N_('Blue Pool'), 12],
  18 + [ N_('Beige'), 13],
  19 + [ N_('Yellow'), 14],
  20 + [ N_('Light Brown'), 15]
10 ] 21 ]
11 22
12 TYPES = [ 23 TYPES = [
app/helpers/cms_helper.rb
@@ -28,12 +28,12 @@ module CmsHelper @@ -28,12 +28,12 @@ module CmsHelper
28 end 28 end
29 29
30 def link_to_article(article) 30 def link_to_article(article)
31 - article_name = short_filename(article.title, 30) 31 + article_name = article.title
32 if article.folder? 32 if article.folder?
33 link_to article_name, {:action => 'view', :id => article.id}, :class => icon_for_article(article) 33 link_to article_name, {:action => 'view', :id => article.id}, :class => icon_for_article(article)
34 else 34 else
35 if article.image? 35 if article.image?
36 - image_tag(icon_for_article(article)) + link_to(article_name, article.url) 36 + image_tag(icon_for_article(article)) + link_to(article_name, article.url)
37 else 37 else
38 link_to article_name, article.url, :class => icon_for_article(article) 38 link_to article_name, article.url, :class => icon_for_article(article)
39 end 39 end
app/helpers/content_viewer_helper.rb
@@ -17,7 +17,7 @@ module ContentViewerHelper @@ -17,7 +17,7 @@ module ContentViewerHelper
17 title = article.display_title if article.kind_of?(UploadedFile) && article.image? 17 title = article.display_title if article.kind_of?(UploadedFile) && article.image?
18 title = article.title if title.blank? 18 title = article.title if title.blank?
19 title = content_tag('h1', h(title), :class => 'title') 19 title = content_tag('h1', h(title), :class => 'title')
20 - if article.belongs_to_blog? 20 + if article.belongs_to_blog? || article.belongs_to_forum?
21 unless args[:no_link] 21 unless args[:no_link]
22 title = content_tag('h1', link_to(article.name, article.url), :class => 'title') 22 title = content_tag('h1', link_to(article.name, article.url), :class => 'title')
23 end 23 end
app/helpers/dates_helper.rb
@@ -35,6 +35,18 @@ module DatesHelper @@ -35,6 +35,18 @@ module DatesHelper
35 end 35 end
36 end 36 end
37 37
  38 + def show_date_month(date, use_numbers = false, year=true)
  39 + if date && use_numbers
  40 + date_format = year ? _('%{month}/%{year}') : _('%{month}/%{day}')
  41 + date_format % { :month => date.month, :year => date.year }
  42 + elsif date
  43 + date_format = year ? _('%{month_name}, %{year}') : _('%{month_name}')
  44 + date_format % { :month_name => month_name(date.month), :year => date.year }
  45 + else
  46 + ''
  47 + end
  48 + end
  49 +
38 # formats a datetime for displaying. 50 # formats a datetime for displaying.
39 def show_time(time) 51 def show_time(time)
40 if time 52 if time
@@ -98,7 +110,11 @@ module DatesHelper @@ -98,7 +110,11 @@ module DatesHelper
98 elsif opts[:previous] 110 elsif opts[:previous]
99 date = date << 1 111 date = date << 1
100 end 112 end
101 - _('%{month} %{year}') % { :year => date.year, :month => month_name(date.month.to_i) } 113 + if opts[:only_month]
  114 + _('%{month}') % {:month => month_name(date.month.to_i) }
  115 + else
  116 + _('%{month} %{year}') % { :year => date.year, :month => month_name(date.month.to_i) }
  117 + end
102 end 118 end
103 119
104 def build_date(year, month, day = 1) 120 def build_date(year, month, day = 1)
@@ -123,7 +139,7 @@ module DatesHelper @@ -123,7 +139,7 @@ module DatesHelper
123 previous_month_date = date - 1.month 139 previous_month_date = date - 1.month
124 140
125 label ||= show_month(previous_month_date.year, previous_month_date.month) 141 label ||= show_month(previous_month_date.year, previous_month_date.month)
126 - link_to label, :year => previous_month_date.year, :month => previous_month_date.month 142 + button(:back, label, {:year => previous_month_date.year, :month => previous_month_date.month})
127 end 143 end
128 144
129 def link_to_next_month(year, month, label = nil) 145 def link_to_next_month(year, month, label = nil)
@@ -131,7 +147,7 @@ module DatesHelper @@ -131,7 +147,7 @@ module DatesHelper
131 next_month_date = date + 1.month 147 next_month_date = date + 1.month
132 148
133 label ||= show_month(next_month_date.year, next_month_date.month) 149 label ||= show_month(next_month_date.year, next_month_date.month)
134 - link_to label, :year => next_month_date.year, :month => next_month_date.month 150 + button(:next, label, {:year => next_month_date.year, :month => next_month_date.month})
135 end 151 end
136 152
137 def pick_date(object, method, options = {}, html_options = {}) 153 def pick_date(object, method, options = {}, html_options = {})
app/helpers/events_helper.rb
1 module EventsHelper 1 module EventsHelper
2 2
3 def list_events(date, events) 3 def list_events(date, events)
4 - return content_tag('em', _("Select a day on the left to display it's events here"), :class => 'select-a-day') unless date  
5 - title = _('Events for %s') % show_date(date) 4 + title = _('Events for %s') % show_date_month(date)
6 content_tag('h2', title) + 5 content_tag('h2', title) +
7 content_tag('div', 6 content_tag('div',
8 (events.any? ? 7 (events.any? ?
9 content_tag('table', events.select { |item| item.display_to?(user) }.map {|item| display_event_in_listing(item)}.join('')) : 8 content_tag('table', events.select { |item| item.display_to?(user) }.map {|item| display_event_in_listing(item)}.join('')) :
10 - content_tag('em', _('No events for this date'), :class => 'no-events') 9 + content_tag('em', _('No events for this month'), :class => 'no-events')
11 ), :id => 'agenda-items' 10 ), :id => 'agenda-items'
12 ) 11 )
13 end 12 end
14 13
15 def display_event_in_listing(article) 14 def display_event_in_listing(article)
16 - content_tag(  
17 - 'tr',  
18 - content_tag('td', link_to(article.name, article.url, :class => icon_for_article(article))),  
19 - :class => 'agenda-item' 15 +
  16 + content_tag( 'tr',
  17 + content_tag('td',
  18 + content_tag('div', show_date(article.start_date) + ( article.end_date.nil? ? '' : (_(" to ") + show_date(article.end_date))),:class => 'event-date' ) +
  19 + content_tag('div',link_to(article.name,article.url),:class => 'event-title') +
  20 + content_tag('div',(article.address.nil? or article.address == '') ? '' : (_('Place: ') + article.address),:class => 'event-place')
  21 + )
20 ) 22 )
21 end 23 end
22 24
app/helpers/folder_helper.rb
@@ -23,6 +23,7 @@ module FolderHelper @@ -23,6 +23,7 @@ module FolderHelper
23 end 23 end
24 24
25 def display_article_in_listing(article, recursive = false, level = 0) 25 def display_article_in_listing(article, recursive = false, level = 0)
  26 + article = FilePresenter.for article
26 article_link = if article.image? 27 article_link = if article.image?
27 link_to('&nbsp;' * (level * 4) + image_tag(icon_for_article(article)) + short_filename(article.name), article.url.merge(:view => true)) 28 link_to('&nbsp;' * (level * 4) + image_tag(icon_for_article(article)) + short_filename(article.name), article.url.merge(:view => true))
28 else 29 else
@@ -42,12 +43,15 @@ module FolderHelper @@ -42,12 +43,15 @@ module FolderHelper
42 end 43 end
43 44
44 def icon_for_article(article) 45 def icon_for_article(article)
45 - icon = article.class.icon_name(article) 46 + article = FilePresenter.for article
  47 + icon = article.respond_to?(:icon_name) ?
  48 + article.icon_name :
  49 + article.class.icon_name(article)
46 if (icon =~ /\//) 50 if (icon =~ /\//)
47 icon 51 icon
48 else 52 else
49 - klasses = 'icon icon-' + icon  
50 - if article.kind_of?(UploadedFile) 53 + klasses = 'icon ' + [icon].flatten.map{|name| 'icon-'+name}.join(' ')
  54 + if article.kind_of?(UploadedFile) || article.kind_of?(FilePresenter)
51 klasses += ' icon-upload-file' 55 klasses += ' icon-upload-file'
52 end 56 end
53 klasses 57 klasses
app/helpers/forgot_password_helper.rb 0 → 100644
@@ -0,0 +1,43 @@ @@ -0,0 +1,43 @@
  1 +module ForgotPasswordHelper
  2 + def plugins_options
  3 + @plugins.dispatch(:change_password_fields)
  4 + end
  5 +
  6 + def user_fields
  7 + %w[login email] + plugins_options.select {|options| options[:model].to_sym == :user }.map { |options| options[:field].to_s }
  8 + end
  9 +
  10 + def person_fields
  11 + %w[] + plugins_options.select {|options| options[:model].to_sym == :person }.map { |options| options[:field].to_s }
  12 + end
  13 +
  14 + def fields
  15 + user_fields + person_fields
  16 + end
  17 +
  18 + def fields_label
  19 + labels = [
  20 + _('Username'),
  21 + _('Email'),
  22 + ] + plugins_options.map { |options| options[:name] }
  23 +
  24 + last = labels.pop
  25 + label = labels.join(', ')
  26 + "#{label} #{_('or')} #{last}"
  27 + end
  28 +
  29 + def build_query(fields, value)
  30 + fields.map {|field| "#{field} = '#{value}'"}.join(' OR ')
  31 + end
  32 +
  33 + def fetch_requestors(value)
  34 + requestors = []
  35 + person_query = build_query(person_fields, value)
  36 + user_query = build_query(user_fields, value)
  37 +
  38 + requestors += Person.where(person_query).where(:environment_id => environment.id) if person_fields.present?
  39 + requestors += User.where(user_query).where(:environment_id => environment.id).map(&:person) if user_fields.present?
  40 + requestors
  41 + end
  42 +
  43 +end
app/helpers/profile_editor_helper.rb
@@ -136,7 +136,7 @@ module ProfileEditorHelper @@ -136,7 +136,7 @@ module ProfileEditorHelper
136 concat( 136 concat(
137 content_tag( 137 content_tag(
138 'div', 138 'div',
139 - capture(&block) + content_tag('br', '', :style => 'clear: left'), 139 + capture(&block) + tag('br', :style => 'clear: left'),
140 :class => 'control-panel') 140 :class => 'control-panel')
141 ) 141 )
142 end 142 end
app/helpers/profile_helper.rb
1 module ProfileHelper 1 module ProfileHelper
2 2
3 def display_field(title, profile, field, force = false) 3 def display_field(title, profile, field, force = false)
4 - if (!force && !profile.active_fields.include?(field.to_s)) ||  
5 - (profile.active_fields.include?(field.to_s) && !profile.public_fields.include?(field.to_s) && (!user || (user != profile && !user.is_a_friend?(profile)))) 4 + unless force || profile.may_display_field_to?(field, user)
6 return '' 5 return ''
7 end 6 end
8 value = profile.send(field) 7 value = profile.send(field)
app/helpers/sweeper_helper.rb
@@ -44,4 +44,30 @@ module SweeperHelper @@ -44,4 +44,30 @@ module SweeperHelper
44 def expire_profile_index(profile) 44 def expire_profile_index(profile)
45 expire_timeout_fragment(profile.relationships_cache_key) 45 expire_timeout_fragment(profile.relationships_cache_key)
46 end 46 end
  47 +
  48 + def expire_blocks_cache(context, causes)
  49 + if context.kind_of?(Profile)
  50 + profile = context
  51 + environment = profile.environment
  52 + else
  53 + environment = context
  54 + profile = nil
  55 + end
  56 +
  57 + blocks_to_expire = []
  58 + if profile
  59 + profile.blocks.each {|block|
  60 + conditions = block.class.expire_on
  61 + blocks_to_expire << block unless (conditions[:profile] & causes).empty?
  62 + }
  63 + end
  64 + environment.blocks.each {|block|
  65 + conditions = block.class.expire_on
  66 + blocks_to_expire << block unless (conditions[:environment] & causes).empty?
  67 + }
  68 +
  69 + blocks_to_expire.uniq!
  70 + BlockSweeper.expire_blocks(blocks_to_expire)
  71 + end
  72 +
47 end 73 end
app/helpers/users_helper.rb 0 → 100644
@@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
  1 +module UsersHelper
  2 +
  3 + FILTER_TRANSLATION = {
  4 + 'all_users' => _('All users'),
  5 + 'admin_users' => _('Admin users'),
  6 + 'activated_users' => _('Activated users'),
  7 + 'deactivated_users' => _('Deativated users'),
  8 + }
  9 +
  10 + def filter_selector(filter, float = 'right')
  11 + options = options_for_select(FILTER_TRANSLATION.map {|key, name| [name, key]}, :selected => filter)
  12 + url_params = url_for(params.merge(:filter => 'FILTER'))
  13 + onchange = "document.location.href = '#{url_params}'.replace('FILTER', this.value)"
  14 + select_field = select_tag(:filter, options, :onchange => onchange)
  15 + content_tag('div',
  16 + content_tag('strong', _('Filter')) + ': ' + select_field,
  17 + :class => "environment-users-customize-search"
  18 + )
  19 + end
  20 +
  21 + def filter_title(filter)
  22 + FILTER_TRANSLATION[filter]
  23 + end
  24 +
  25 +end
app/models/action_tracker_notification.rb
@@ -3,7 +3,7 @@ class ActionTrackerNotification &lt; ActiveRecord::Base @@ -3,7 +3,7 @@ class ActionTrackerNotification &lt; ActiveRecord::Base
3 belongs_to :profile 3 belongs_to :profile
4 belongs_to :action_tracker, :class_name => 'ActionTracker::Record', :foreign_key => 'action_tracker_id' 4 belongs_to :action_tracker, :class_name => 'ActionTracker::Record', :foreign_key => 'action_tracker_id'
5 5
6 - has_many :comments, :through => :action_tracker, :class_name => 'Comment', :foreign_key => 'source_id' 6 + delegate :comments, :to => :action_tracker, :allow_nil => true
7 7
8 validates_presence_of :profile_id, :action_tracker_id 8 validates_presence_of :profile_id, :action_tracker_id
9 validates_uniqueness_of :action_tracker_id, :scope => :profile_id 9 validates_uniqueness_of :action_tracker_id, :scope => :profile_id
app/models/approve_comment.rb
@@ -6,7 +6,7 @@ class ApproveComment &lt; Task @@ -6,7 +6,7 @@ class ApproveComment &lt; Task
6 validates_presence_of :comment_attributes 6 validates_presence_of :comment_attributes
7 7
8 def comment 8 def comment
9 - @comment ||= Comment.new(JSON.parse(self.comment_attributes)) unless self.comment_attributes.nil? 9 + @comment ||= Comment.new(ActiveSupport::JSON.decode(self.comment_attributes)) unless self.comment_attributes.nil?
10 end 10 end
11 11
12 def requestor_name 12 def requestor_name
@@ -42,9 +42,9 @@ class ApproveComment &lt; Task @@ -42,9 +42,9 @@ class ApproveComment &lt; Task
42 def information 42 def information
43 if article 43 if article
44 if requestor 44 if requestor
45 - {:message => _('%{requestor} commented on the the article: %{linked_subject}.')} 45 + {:message => _('%{requestor} commented on the article: %{linked_subject}.')}
46 else 46 else
47 - { :message => _('%{requestor} commented on the the article: %{linked_subject}.'), 47 + { :message => _('%{requestor} commented on the article: %{linked_subject}.'),
48 :variables => {:requestor => requestor_name} } 48 :variables => {:requestor => requestor_name} }
49 end 49 end
50 else 50 else
app/models/article.rb
@@ -4,6 +4,8 @@ class Article &lt; ActiveRecord::Base @@ -4,6 +4,8 @@ class Article &lt; ActiveRecord::Base
4 4
5 attr_accessible :name, :body, :abstract, :profile, :tag_list, :parent 5 attr_accessible :name, :body, :abstract, :profile, :tag_list, :parent
6 6
  7 + acts_as_having_image
  8 +
7 SEARCHABLE_FIELDS = { 9 SEARCHABLE_FIELDS = {
8 :name => 10, 10 :name => 10,
9 :abstract => 3, 11 :abstract => 3,
@@ -59,7 +61,7 @@ class Article &lt; ActiveRecord::Base @@ -59,7 +61,7 @@ class Article &lt; ActiveRecord::Base
59 has_many :article_categorizations, :conditions => [ 'articles_categories.virtual = ?', false ] 61 has_many :article_categorizations, :conditions => [ 'articles_categories.virtual = ?', false ]
60 has_many :categories, :through => :article_categorizations 62 has_many :categories, :through => :article_categorizations
61 63
62 - has_many :article_categorizations_including_virtual, :class_name => 'ArticleCategorization', :dependent => :destroy 64 + has_many :article_categorizations_including_virtual, :class_name => 'ArticleCategorization'
63 has_many :categories_including_virtual, :through => :article_categorizations_including_virtual, :source => :category 65 has_many :categories_including_virtual, :through => :article_categorizations_including_virtual, :source => :category
64 66
65 acts_as_having_settings :field => :setting 67 acts_as_having_settings :field => :setting
@@ -156,8 +158,12 @@ class Article &lt; ActiveRecord::Base @@ -156,8 +158,12 @@ class Article &lt; ActiveRecord::Base
156 end 158 end
157 end 159 end
158 160
  161 + def css_class_list
  162 + [self.class.name.to_css_class]
  163 + end
  164 +
159 def css_class_name 165 def css_class_name
160 - self.class.name.underscore.dasherize 166 + [css_class_list].flatten.compact.join(' ')
161 end 167 end
162 168
163 def pending_categorizations 169 def pending_categorizations
@@ -190,7 +196,7 @@ class Article &lt; ActiveRecord::Base @@ -190,7 +196,7 @@ class Article &lt; ActiveRecord::Base
190 pending_categorizations.clear 196 pending_categorizations.clear
191 end 197 end
192 198
193 - acts_as_taggable 199 + acts_as_taggable
194 N_('Tag list') 200 N_('Tag list')
195 201
196 acts_as_filesystem 202 acts_as_filesystem
@@ -268,7 +274,7 @@ class Article &lt; ActiveRecord::Base @@ -268,7 +274,7 @@ class Article &lt; ActiveRecord::Base
268 end 274 end
269 275
270 # returns the data of the article. Must be overriden in each subclass to 276 # returns the data of the article. Must be overriden in each subclass to
271 - # provide the correct content for the article. 277 + # provide the correct content for the article.
272 def data 278 def data
273 body 279 body
274 end 280 end
@@ -282,6 +288,11 @@ class Article &lt; ActiveRecord::Base @@ -282,6 +288,11 @@ class Article &lt; ActiveRecord::Base
282 'text-html' 288 'text-html'
283 end 289 end
284 290
  291 + # TODO Migrate the class method icon_name to instance methods.
  292 + def icon_name
  293 + self.class.icon_name(self)
  294 + end
  295 +
285 def mime_type 296 def mime_type
286 'text/html' 297 'text/html'
287 end 298 end
@@ -310,6 +321,10 @@ class Article &lt; ActiveRecord::Base @@ -310,6 +321,10 @@ class Article &lt; ActiveRecord::Base
310 def belongs_to_blog? 321 def belongs_to_blog?
311 self.parent and self.parent.blog? 322 self.parent and self.parent.blog?
312 end 323 end
  324 +
  325 + def belongs_to_forum?
  326 + self.parent and self.parent.forum?
  327 + end
313 328
314 def info_from_last_update 329 def info_from_last_update
315 last_comment = comments.last 330 last_comment = comments.last
@@ -325,7 +340,7 @@ class Article &lt; ActiveRecord::Base @@ -325,7 +340,7 @@ class Article &lt; ActiveRecord::Base
325 end 340 end
326 341
327 def view_url 342 def view_url
328 - @view_url ||= image? ? url.merge(:view => true) : url 343 + @view_url ||= is_a?(UploadedFile) ? url.merge(:view => true) : url
329 end 344 end
330 345
331 def comment_url_structure(comment, action = :edit) 346 def comment_url_structure(comment, action = :edit)
@@ -340,24 +355,18 @@ class Article &lt; ActiveRecord::Base @@ -340,24 +355,18 @@ class Article &lt; ActiveRecord::Base
340 true 355 true
341 end 356 end
342 357
343 - def folder?  
344 - false  
345 - end  
346 -  
347 - def blog?  
348 - false  
349 - end  
350 -  
351 - def forum? 358 + def has_posts?
352 false 359 false
353 end 360 end
354 361
355 - def uploaded_file?  
356 - false 362 + def download? view = nil
  363 + (self.uploaded_file? and not self.image?) or
  364 + (self.image? and view.blank?) or
  365 + (not self.uploaded_file? and self.mime_type != 'text/html')
357 end 366 end
358 367
359 - def has_posts?  
360 - false 368 + def download_headers
  369 + {}
361 end 370 end
362 371
363 scope :native_translations, :conditions => { :translation_of_id => nil } 372 scope :native_translations, :conditions => { :translation_of_id => nil }
@@ -444,6 +453,7 @@ class Article &lt; ActiveRecord::Base @@ -444,6 +453,7 @@ class Article &lt; ActiveRecord::Base
444 scope :galleries, :conditions => { :type => 'Gallery' } 453 scope :galleries, :conditions => { :type => 'Gallery' }
445 scope :images, :conditions => { :is_image => true } 454 scope :images, :conditions => { :is_image => true }
446 scope :text_articles, :conditions => [ 'articles.type IN (?)', text_article_types ] 455 scope :text_articles, :conditions => [ 'articles.type IN (?)', text_article_types ]
  456 + scope :with_types, lambda { |types| { :conditions => [ 'articles.type IN (?)', types ] } }
447 457
448 scope :more_popular, :order => 'hits DESC' 458 scope :more_popular, :order => 'hits DESC'
449 scope :more_comments, :order => "comments_count DESC" 459 scope :more_comments, :order => "comments_count DESC"
@@ -586,6 +596,22 @@ class Article &lt; ActiveRecord::Base @@ -586,6 +596,22 @@ class Article &lt; ActiveRecord::Base
586 false 596 false
587 end 597 end
588 598
  599 + def folder?
  600 + false
  601 + end
  602 +
  603 + def blog?
  604 + false
  605 + end
  606 +
  607 + def forum?
  608 + false
  609 + end
  610 +
  611 + def uploaded_file?
  612 + false
  613 + end
  614 +
589 def author 615 def author
590 if versions.empty? 616 if versions.empty?
591 last_changed_by 617 last_changed_by
@@ -725,6 +751,10 @@ class Article &lt; ActiveRecord::Base @@ -725,6 +751,10 @@ class Article &lt; ActiveRecord::Base
725 751
726 delegate :region, :region_id, :environment, :environment_id, :to => :profile, :allow_nil => true 752 delegate :region, :region_id, :environment, :environment_id, :to => :profile, :allow_nil => true
727 753
  754 + def has_macro?
  755 + true
  756 + end
  757 +
728 private 758 private
729 759
730 def sanitize_tag_list 760 def sanitize_tag_list
app/models/article_block.rb
@@ -12,7 +12,7 @@ class ArticleBlock &lt; Block @@ -12,7 +12,7 @@ class ArticleBlock &lt; Block
12 block = self 12 block = self
13 proc do 13 proc do
14 block_title(block.title) + 14 block_title(block.title) +
15 - (block.article ? article_to_html(block.article, 15 + (block.article ? article_to_html(FilePresenter.for(block.article),
16 :gallery_view => false, 16 :gallery_view => false,
17 :inside_block => block, # For Blogs and folders 17 :inside_block => block, # For Blogs and folders
18 :format => block.visualization_format # For Articles and contents 18 :format => block.visualization_format # For Articles and contents
@@ -23,7 +23,7 @@ class ArticleBlock &lt; Block @@ -23,7 +23,7 @@ class ArticleBlock &lt; Block
23 def article_id 23 def article_id
24 self.settings[:article_id] 24 self.settings[:article_id]
25 end 25 end
26 - 26 +
27 def article_id= value 27 def article_id= value
28 self.settings[:article_id] = value.blank? ? nil : value.to_i 28 self.settings[:article_id] = value.blank? ? nil : value.to_i
29 end 29 end
@@ -49,8 +49,8 @@ class ArticleBlock &lt; Block @@ -49,8 +49,8 @@ class ArticleBlock &lt; Block
49 end 49 end
50 50
51 def available_articles 51 def available_articles
52 - return [] if self.box.nil? or self.box.owner.nil?  
53 - self.box.owner.kind_of?(Environment) ? self.box.owner.portal_community.articles : self.box.owner.articles 52 + return [] if self.owner.nil?
  53 + self.owner.kind_of?(Environment) ? self.owner.portal_community.articles : self.owner.articles
54 end 54 end
55 55
56 def posts_per_page 56 def posts_per_page
@@ -63,4 +63,9 @@ class ArticleBlock &lt; Block @@ -63,4 +63,9 @@ class ArticleBlock &lt; Block
63 end 63 end
64 64
65 settings_items :visualization_format, :type => :string, :default => 'short' 65 settings_items :visualization_format, :type => :string, :default => 'short'
  66 +
  67 + def self.expire_on
  68 + { :profile => [:article], :environment => [:article] }
  69 + end
  70 +
66 end 71 end
app/models/block.rb
@@ -140,4 +140,19 @@ class Block &lt; ActiveRecord::Base @@ -140,4 +140,19 @@ class Block &lt; ActiveRecord::Base
140 4.hours 140 4.hours
141 end 141 end
142 142
  143 + def has_macro?
  144 + false
  145 + end
  146 +
  147 + # Override in your subclasses.
  148 + # Define which events and context should cause the block cache to expire
  149 + # Possible events are: :article, :profile, :friendship, :category
  150 + # Possible contexts are: :profile, :environment
  151 + def self.expire_on
  152 + {
  153 + :profile => [],
  154 + :environment => []
  155 + }
  156 + end
  157 +
143 end 158 end
app/models/blog_archives_block.rb
@@ -45,4 +45,7 @@ class BlogArchivesBlock &lt; Block @@ -45,4 +45,7 @@ class BlogArchivesBlock &lt; Block
45 content_tag('div', link_to(_('Subscribe RSS Feed'), owner_blog.feed.url), :class => 'subscribe-feed') 45 content_tag('div', link_to(_('Subscribe RSS Feed'), owner_blog.feed.url), :class => 'subscribe-feed')
46 end 46 end
47 47
  48 + def self.expire_on
  49 + { :profile => [:article], :environment => [:article] }
  50 + end
48 end 51 end
app/models/box.rb
@@ -3,12 +3,15 @@ class Box &lt; ActiveRecord::Base @@ -3,12 +3,15 @@ class Box &lt; ActiveRecord::Base
3 acts_as_list :scope => 'owner_id = #{owner_id} and owner_type = \'#{owner_type}\'' 3 acts_as_list :scope => 'owner_id = #{owner_id} and owner_type = \'#{owner_type}\''
4 has_many :blocks, :dependent => :destroy, :order => 'position' 4 has_many :blocks, :dependent => :destroy, :order => 'position'
5 5
  6 + include Noosfero::Plugin::HotSpot
  7 +
6 def environment 8 def environment
7 owner ? (owner.kind_of?(Environment) ? owner : owner.environment) : nil 9 owner ? (owner.kind_of?(Environment) ? owner : owner.environment) : nil
8 end 10 end
9 11
10 def acceptable_blocks 12 def acceptable_blocks
11 - to_css_class_name central? ? Box.acceptable_center_blocks : Box.acceptable_side_blocks 13 + blocks_classes = central? ? Box.acceptable_center_blocks + plugins.dispatch(:extra_blocks, :position => 1) : Box.acceptable_side_blocks + plugins.dispatch(:extra_blocks, :position => [2, 3])
  14 + to_css_class_name(blocks_classes)
12 end 15 end
13 16
14 def central? 17 def central?
@@ -74,8 +77,8 @@ class Box &lt; ActiveRecord::Base @@ -74,8 +77,8 @@ class Box &lt; ActiveRecord::Base
74 77
75 private 78 private
76 79
77 - def to_css_class_name(blocks)  
78 - blocks.map{ |block| block.to_s.underscore.tr('_', '-') } 80 + def to_css_class_name(blocks_classes)
  81 + blocks_classes.map{ |block_class| block_class.name.to_css_class }
79 end 82 end
80 83
81 end 84 end
app/models/categories_block.rb
@@ -35,4 +35,7 @@ class CategoriesBlock &lt; Block @@ -35,4 +35,7 @@ class CategoriesBlock &lt; Block
35 end 35 end
36 end 36 end
37 37
  38 + def self.expire_on
  39 + { :profile => [], :environment => [:category] }
  40 + end
38 end 41 end
app/models/category.rb
@@ -9,13 +9,13 @@ class Category &lt; ActiveRecord::Base @@ -9,13 +9,13 @@ class Category &lt; ActiveRecord::Base
9 :slug => 1, 9 :slug => 1,
10 } 10 }
11 11
12 - validates_exclusion_of :slug, :in => [ 'index' ], :message => N_('%{fn} cannot be like that.').fix_i18n 12 + validates_exclusion_of :slug, :in => [ 'index' ], :message => N_('{fn} cannot be like that.').fix_i18n
13 validates_presence_of :name, :environment_id 13 validates_presence_of :name, :environment_id
14 - validates_uniqueness_of :slug,:scope => [ :environment_id, :parent_id ], :message => N_('%{fn} is already being used by another category.').fix_i18n 14 + validates_uniqueness_of :slug,:scope => [ :environment_id, :parent_id ], :message => N_('{fn} is already being used by another category.').fix_i18n
15 belongs_to :environment 15 belongs_to :environment
16 16
17 - validates_inclusion_of :display_color, :in => [ 1, 2, 3, 4, nil ]  
18 - validates_uniqueness_of :display_color, :scope => :environment_id, :if => (lambda { |cat| ! cat.display_color.nil? }), :message => N_('%{fn} was already assigned to another category.').fix_i18n 17 + validates_inclusion_of :display_color, :in => 1..15, :allow_nil => true
  18 + validates_uniqueness_of :display_color, :scope => :environment_id, :if => (lambda { |cat| ! cat.display_color.nil? }), :message => N_('{fn} was already assigned to another category.').fix_i18n
19 19
20 # Finds all top level categories for a given environment. 20 # Finds all top level categories for a given environment.
21 scope :top_level_for, lambda { |environment| 21 scope :top_level_for, lambda { |environment|
@@ -24,23 +24,15 @@ class Category &lt; ActiveRecord::Base @@ -24,23 +24,15 @@ class Category &lt; ActiveRecord::Base
24 24
25 scope :on_level, lambda { |parent| {:conditions => {:parent_id => parent}} } 25 scope :on_level, lambda { |parent| {:conditions => {:parent_id => parent}} }
26 26
27 - scope :sub_categories, lambda { |category|  
28 - {:conditions => ['categories.path LIKE ? AND categories.id != ?', "%#{category.slug}%", category.id]}  
29 - }  
30 -  
31 - scope :sub_tree, lambda { |category|  
32 - {:conditions => ['categories.path LIKE ?', "%#{category.slug}%"]}  
33 - }  
34 -  
35 acts_as_filesystem 27 acts_as_filesystem
36 28
37 - has_many :article_categorizations, :dependent => :destroy 29 + has_many :article_categorizations
38 has_many :articles, :through => :article_categorizations 30 has_many :articles, :through => :article_categorizations
39 has_many :comments, :through => :articles 31 has_many :comments, :through => :articles
40 32
41 has_many :events, :through => :article_categorizations, :class_name => 'Event', :source => :article 33 has_many :events, :through => :article_categorizations, :class_name => 'Event', :source => :article
42 34
43 - has_many :profile_categorizations, :dependent => :destroy 35 + has_many :profile_categorizations
44 has_many :profiles, :through => :profile_categorizations, :source => :profile 36 has_many :profiles, :through => :profile_categorizations, :source => :profile
45 has_many :enterprises, :through => :profile_categorizations, :source => :profile, :class_name => 'Enterprise' 37 has_many :enterprises, :through => :profile_categorizations, :source => :profile, :class_name => 'Enterprise'
46 has_many :people, :through => :profile_categorizations, :source => :profile, :class_name => 'Person' 38 has_many :people, :through => :profile_categorizations, :source => :profile, :class_name => 'Person'
app/models/change_password.rb
1 class ChangePassword < Task 1 class ChangePassword < Task
2 2
3 - attr_accessor :login, :email, :password, :password_confirmation, :environment_id 3 + attr_accessor :password, :password_confirmation
4 4
5 def self.human_attribute_name(attrib) 5 def self.human_attribute_name(attrib)
6 case attrib.to_sym 6 case attrib.to_sym
7 - when :login  
8 - _('Username')  
9 - when :email  
10 - _('e-mail')  
11 when :password 7 when :password
12 _('Password') 8 _('Password')
13 when :password_confirmation 9 when :password_confirmation
@@ -17,29 +13,7 @@ class ChangePassword &lt; Task @@ -17,29 +13,7 @@ class ChangePassword &lt; Task
17 end 13 end
18 end 14 end
19 15
20 - ###################################################  
21 - # validations for creating a ChangePassword task  
22 -  
23 - validates_presence_of :login, :email, :environment_id, :on => :create, :message => _('must be filled in')  
24 -  
25 - validates_format_of :email, :on => :create, :with => Noosfero::Constants::EMAIL_FORMAT, :if => (lambda { |obj| !obj.email.blank? })  
26 -  
27 - validates_each :login, :on => :create do |data,attr,value|  
28 - unless data.login.blank? || data.email.blank?  
29 - user = User.find_by_login_and_environment_id(data.login, data.environment_id)  
30 - if user.nil?  
31 - data.errors.add(:login, _('is invalid or user does not exists.'))  
32 - else  
33 - if user.email != data.email  
34 - data.errors.add(:email, _('does not match the username you filled in'))  
35 - end  
36 - end  
37 - end  
38 - end  
39 -  
40 - before_validation(:on => :create) do |change_password|  
41 - change_password.requestor = Person.find_by_identifier_and_environment_id(change_password.login, change_password.environment_id)  
42 - end 16 + validates_presence_of :requestor
43 17
44 ################################################### 18 ###################################################
45 # validations for updating a ChangePassword task 19 # validations for updating a ChangePassword task
@@ -49,6 +23,10 @@ class ChangePassword &lt; Task @@ -49,6 +23,10 @@ class ChangePassword &lt; Task
49 validates_presence_of :password_confirmation, :on => :update, :if => lambda { |change| change.status != Task::Status::CANCELLED } 23 validates_presence_of :password_confirmation, :on => :update, :if => lambda { |change| change.status != Task::Status::CANCELLED }
50 validates_confirmation_of :password, :if => lambda { |change| change.status != Task::Status::CANCELLED } 24 validates_confirmation_of :password, :if => lambda { |change| change.status != Task::Status::CANCELLED }
51 25
  26 + def environment
  27 + requestor.environment unless requestor.nil?
  28 + end
  29 +
52 def title 30 def title
53 _("Change password") 31 _("Change password")
54 end 32 end
@@ -87,12 +65,8 @@ class ChangePassword &lt; Task @@ -87,12 +65,8 @@ class ChangePassword &lt; Task
87 url = url_for(:host => hostname, :controller => 'account', :action => 'new_password', :code => code) 65 url = url_for(:host => hostname, :controller => 'account', :action => 'new_password', :code => code)
88 66
89 proc do 67 proc do
90 - _("In order to change your password, please visit the following address:\n\n%s") % url 68 + _("In order to change your password, please visit the following address:\n\n%s\n\nIf you did not required any change to your password just desconsider this email.") % url
91 end 69 end
92 end 70 end
93 71
94 - def environment  
95 - self.requestor.environment  
96 - end  
97 -  
98 end 72 end
app/models/comment.rb
@@ -16,9 +16,7 @@ class Comment &lt; ActiveRecord::Base @@ -16,9 +16,7 @@ class Comment &lt; ActiveRecord::Base
16 has_many :children, :class_name => 'Comment', :foreign_key => 'reply_of_id', :dependent => :destroy 16 has_many :children, :class_name => 'Comment', :foreign_key => 'reply_of_id', :dependent => :destroy
17 belongs_to :reply_of, :class_name => 'Comment', :foreign_key => 'reply_of_id' 17 belongs_to :reply_of, :class_name => 'Comment', :foreign_key => 'reply_of_id'
18 18
19 - scope :without_spam, :conditions => ['spam IS NULL OR spam = ?', false]  
20 scope :without_reply, :conditions => ['reply_of_id IS NULL'] 19 scope :without_reply, :conditions => ['reply_of_id IS NULL']
21 - scope :spam, :conditions => ['spam = ?', true]  
22 20
23 # unauthenticated authors: 21 # unauthenticated authors:
24 validates_presence_of :name, :if => (lambda { |record| !record.email.blank? }) 22 validates_presence_of :name, :if => (lambda { |record| !record.email.blank? })
@@ -29,7 +27,7 @@ class Comment &lt; ActiveRecord::Base @@ -29,7 +27,7 @@ class Comment &lt; ActiveRecord::Base
29 validates_presence_of :author_id, :if => (lambda { |rec| rec.name.blank? && rec.email.blank? }) 27 validates_presence_of :author_id, :if => (lambda { |rec| rec.name.blank? && rec.email.blank? })
30 validates_each :name do |rec,attribute,value| 28 validates_each :name do |rec,attribute,value|
31 if rec.author_id && (!rec.name.blank? || !rec.email.blank?) 29 if rec.author_id && (!rec.name.blank? || !rec.email.blank?)
32 - rec.errors.add(:name, _('%{fn} can only be informed for unauthenticated authors').fix_i18n) 30 + rec.errors.add(:name, _('{fn} can only be informed for unauthenticated authors').fix_i18n)
33 end 31 end
34 end 32 end
35 33
@@ -104,10 +102,21 @@ class Comment &lt; ActiveRecord::Base @@ -104,10 +102,21 @@ class Comment &lt; ActiveRecord::Base
104 end 102 end
105 103
106 delegate :environment, :to => :profile 104 delegate :environment, :to => :profile
107 - delegate :profile, :to => :source 105 + delegate :profile, :to => :source, :allow_nil => true
108 106
109 include Noosfero::Plugin::HotSpot 107 include Noosfero::Plugin::HotSpot
110 108
  109 + include Spammable
  110 +
  111 + def after_spam!
  112 + SpammerLogger.log(ip_address, self)
  113 + Delayed::Job.enqueue(CommentHandler.new(self.id, :marked_as_spam))
  114 + end
  115 +
  116 + def after_ham!
  117 + Delayed::Job.enqueue(CommentHandler.new(self.id, :marked_as_ham))
  118 + end
  119 +
111 def verify_and_notify 120 def verify_and_notify
112 check_for_spam 121 check_for_spam
113 unless spam? 122 unless spam?
@@ -115,10 +124,6 @@ class Comment &lt; ActiveRecord::Base @@ -115,10 +124,6 @@ class Comment &lt; ActiveRecord::Base
115 end 124 end
116 end 125 end
117 126
118 - def check_for_spam  
119 - plugins.dispatch(:check_comment_for_spam, self)  
120 - end  
121 -  
122 def notify_by_mail 127 def notify_by_mail
123 if source.kind_of?(Article) && article.notify_comments? 128 if source.kind_of?(Article) && article.notify_comments?
124 if !notification_emails.empty? 129 if !notification_emails.empty?
@@ -171,37 +176,6 @@ class Comment &lt; ActiveRecord::Base @@ -171,37 +176,6 @@ class Comment &lt; ActiveRecord::Base
171 @rejected = true 176 @rejected = true
172 end 177 end
173 178
174 - def spam?  
175 - !spam.nil? && spam  
176 - end  
177 -  
178 - def ham?  
179 - !spam.nil? && !spam  
180 - end  
181 -  
182 - def spam!  
183 - self.spam = true  
184 - self.save!  
185 - SpammerLogger.log(ip_address, self)  
186 - Delayed::Job.enqueue(CommentHandler.new(self.id, :marked_as_spam))  
187 - self  
188 - end  
189 -  
190 - def ham!  
191 - self.spam = false  
192 - self.save!  
193 - Delayed::Job.enqueue(CommentHandler.new(self.id, :marked_as_ham))  
194 - self  
195 - end  
196 -  
197 - def marked_as_spam  
198 - plugins.dispatch(:comment_marked_as_spam, self)  
199 - end  
200 -  
201 - def marked_as_ham  
202 - plugins.dispatch(:comment_marked_as_ham, self)  
203 - end  
204 -  
205 def need_moderation? 179 def need_moderation?
206 article.moderate_comments? && (author.nil? || article.author != author) 180 article.moderate_comments? && (author.nil? || article.author != author)
207 end 181 end
app/models/create_enterprise.rb
@@ -42,14 +42,14 @@ class CreateEnterprise &lt; Task @@ -42,14 +42,14 @@ class CreateEnterprise &lt; Task
42 def validator_correct_region 42 def validator_correct_region
43 if self.region && self.target 43 if self.region && self.target
44 unless self.region.validators.include?(self.target) || self.target_type == "Environment" 44 unless self.region.validators.include?(self.target) || self.target_type == "Environment"
45 - self.errors.add(:target, _('%{fn} is not a validator for the chosen region').fix_i18n) 45 + self.errors.add(:target, _('{fn} is not a validator for the chosen region').fix_i18n)
46 end 46 end
47 end 47 end
48 end 48 end
49 49
50 def not_used_identifier 50 def not_used_identifier
51 if self.status != Task::Status::CANCELLED && self.identifier && Profile.exists?(:identifier => self.identifier) 51 if self.status != Task::Status::CANCELLED && self.identifier && Profile.exists?(:identifier => self.identifier)
52 - self.errors.add(:identifier, _('%{fn} is already being as identifier by another enterprise, organization or person.').fix_i18n) 52 + self.errors.add(:identifier, _('{fn} is already being as identifier by another enterprise, organization or person.').fix_i18n)
53 end 53 end
54 end 54 end
55 55
app/models/domain.rb
@@ -14,7 +14,7 @@ class Domain &lt; ActiveRecord::Base @@ -14,7 +14,7 @@ class Domain &lt; ActiveRecord::Base
14 14
15 # <tt>name</tt> must be sequences of alphanumeric characters (a to z, 15 # <tt>name</tt> must be sequences of alphanumeric characters (a to z,
16 # 0 to 9), plus '_' or '-', separated by dots. Letters must be lowercase. 16 # 0 to 9), plus '_' or '-', separated by dots. Letters must be lowercase.
17 - validates_format_of :name, :with => /^([a-z0-9_-]+\.)+[a-z0-9_-]+$/, :message => N_('%{fn} must be composed of sequences of lowercase letters (a to z), numbers (0 to 9), "_" and "-", separated by dots.').fix_i18n 17 + validates_format_of :name, :with => /^([a-z0-9_-]+\.)+[a-z0-9_-]+$/, :message => N_('{fn} must be composed of sequences of lowercase letters (a to z), numbers (0 to 9), "_" and "-", separated by dots.').fix_i18n
18 18
19 # checks validations that could not be expressed using Rails' predefined 19 # checks validations that could not be expressed using Rails' predefined
20 # validations. In particular: 20 # validations. In particular:
@@ -23,7 +23,7 @@ class Domain &lt; ActiveRecord::Base @@ -23,7 +23,7 @@ class Domain &lt; ActiveRecord::Base
23 23
24 def no_www 24 def no_www
25 if self.name =~ /^www\./ 25 if self.name =~ /^www\./
26 - self.errors.add(:name, _('%{fn} must not start with www.').fix_i18n) 26 + self.errors.add(:name, _('{fn} must not start with www.').fix_i18n)
27 end 27 end
28 end 28 end
29 29
app/models/enterprise.rb
@@ -135,7 +135,7 @@ class Enterprise &lt; Organization @@ -135,7 +135,7 @@ class Enterprise &lt; Organization
135 [ProfileImageBlock.new, LinkListBlock.new(:links => links)], 135 [ProfileImageBlock.new, LinkListBlock.new(:links => links)],
136 [] 136 []
137 ] 137 ]
138 - if !environment.enabled?('disable_products_for_enterprises') 138 + if environment.enabled?('products_for_enterprises')
139 blocks[2].unshift ProductsBlock.new 139 blocks[2].unshift ProductsBlock.new
140 end 140 end
141 blocks 141 blocks
app/models/environment.rb
@@ -97,7 +97,6 @@ class Environment &lt; ActiveRecord::Base @@ -97,7 +97,6 @@ class Environment &lt; ActiveRecord::Base
97 'disable_asset_communities' => _('Disable search for communities'), 97 'disable_asset_communities' => _('Disable search for communities'),
98 'disable_asset_products' => _('Disable search for products'), 98 'disable_asset_products' => _('Disable search for products'),
99 'disable_asset_events' => _('Disable search for events'), 99 'disable_asset_events' => _('Disable search for events'),
100 - 'disable_products_for_enterprises' => _('Disable products for enterprises'),  
101 'disable_categories' => _('Disable categories'), 100 'disable_categories' => _('Disable categories'),
102 'disable_header_and_footer' => _('Disable header/footer editing by users'), 101 'disable_header_and_footer' => _('Disable header/footer editing by users'),
103 'disable_gender_icon' => _('Disable gender icon'), 102 'disable_gender_icon' => _('Disable gender icon'),
@@ -105,9 +104,13 @@ class Environment &lt; ActiveRecord::Base @@ -105,9 +104,13 @@ class Environment &lt; ActiveRecord::Base
105 'disable_select_city_for_contact' => _('Disable state/city select for contact form'), 104 'disable_select_city_for_contact' => _('Disable state/city select for contact form'),
106 'disable_contact_person' => _('Disable contact for people'), 105 'disable_contact_person' => _('Disable contact for people'),
107 'disable_contact_community' => _('Disable contact for groups/communities'), 106 'disable_contact_community' => _('Disable contact for groups/communities'),
108 - 'enterprise_registration' => _('Enterprise registration'),  
109 107
110 - 'enterprise_activation' => _('Enable activation of enterprises'), 108 + 'products_for_enterprises' => __('Enable products for enterprises'),
  109 + 'enterprise_registration' => __('Enterprise registration'),
  110 + 'enterprise_activation' => __('Enable activation of enterprises'),
  111 + 'enterprises_are_disabled_when_created' => __('Enterprises are disabled when created'),
  112 + 'enterprises_are_validated_when_created' => __('Enterprises are validated when created'),
  113 +
111 'media_panel' => _('Media panel in WYSIWYG editor'), 114 'media_panel' => _('Media panel in WYSIWYG editor'),
112 'select_preferred_domain' => _('Select preferred domains per profile'), 115 'select_preferred_domain' => _('Select preferred domains per profile'),
113 'use_portal_community' => _('Use the portal as news source for front page'), 116 'use_portal_community' => _('Use the portal as news source for front page'),
@@ -120,15 +123,15 @@ class Environment &lt; ActiveRecord::Base @@ -120,15 +123,15 @@ class Environment &lt; ActiveRecord::Base
120 'organizations_are_moderated_by_default' => _("Organizations have moderated publication by default"), 123 'organizations_are_moderated_by_default' => _("Organizations have moderated publication by default"),
121 'enable_organization_url_change' => _("Allow organizations to change their URL"), 124 'enable_organization_url_change' => _("Allow organizations to change their URL"),
122 'admin_must_approve_new_communities' => _("Admin must approve creation of communities"), 125 'admin_must_approve_new_communities' => _("Admin must approve creation of communities"),
123 - 'enterprises_are_disabled_when_created' => _('Enterprises are disabled when created'),  
124 - 'enterprises_are_validated_when_created' => _('Enterprises are validated when created'),  
125 'show_balloon_with_profile_links_when_clicked' => _('Show a balloon with profile links when a profile image is clicked'), 126 'show_balloon_with_profile_links_when_clicked' => _('Show a balloon with profile links when a profile image is clicked'),
126 'xmpp_chat' => _('XMPP/Jabber based chat'), 127 'xmpp_chat' => _('XMPP/Jabber based chat'),
127 'show_zoom_button_on_article_images' => _('Show a zoom link on all article images'), 128 'show_zoom_button_on_article_images' => _('Show a zoom link on all article images'),
128 'captcha_for_logged_users' => _('Ask captcha when a logged user comments too'), 129 'captcha_for_logged_users' => _('Ask captcha when a logged user comments too'),
129 'skip_new_user_email_confirmation' => _('Skip e-mail confirmation for new users'), 130 'skip_new_user_email_confirmation' => _('Skip e-mail confirmation for new users'),
130 'send_welcome_email_to_new_users' => _('Send welcome e-mail to new users'), 131 'send_welcome_email_to_new_users' => _('Send welcome e-mail to new users'),
131 - 'allow_change_of_redirection_after_login' => _('Allow users to set the page to redirect after login') 132 + 'allow_change_of_redirection_after_login' => _('Allow users to set the page to redirect after login'),
  133 + 'display_my_communities_on_user_menu' => _('Display on menu the list of communities the user can manage'),
  134 + 'display_my_enterprises_on_user_menu' => _('Display on menu the list of enterprises the user can manage')
132 } 135 }
133 end 136 end
134 137
@@ -169,7 +172,7 @@ class Environment &lt; ActiveRecord::Base @@ -169,7 +172,7 @@ class Environment &lt; ActiveRecord::Base
169 172
170 # One Environment can be reached by many domains 173 # One Environment can be reached by many domains
171 has_many :domains, :as => :owner 174 has_many :domains, :as => :owner
172 - has_many :profiles 175 + has_many :profiles, :dependent => :destroy
173 176
174 has_many :organizations 177 has_many :organizations
175 has_many :enterprises 178 has_many :enterprises
@@ -277,7 +280,7 @@ class Environment &lt; ActiveRecord::Base @@ -277,7 +280,7 @@ class Environment &lt; ActiveRecord::Base
277 settings_items :restrict_to_access_control_origins, :default => false 280 settings_items :restrict_to_access_control_origins, :default => false
278 # Set this according to http://www.w3.org/TR/cors/. Headers are set at every response 281 # Set this according to http://www.w3.org/TR/cors/. Headers are set at every response
279 # For multiple domains acts as suggested in http://stackoverflow.com/questions/1653308/access-control-allow-origin-multiple-origin-domains 282 # For multiple domains acts as suggested in http://stackoverflow.com/questions/1653308/access-control-allow-origin-multiple-origin-domains
280 - settings_items :access_control_allow_origin, :type => Array 283 + settings_items :access_control_allow_origin, :type => Array, :default => []
281 settings_items :access_control_allow_methods, :type => String 284 settings_items :access_control_allow_methods, :type => String
282 285
283 def news_amount_by_folder=(amount) 286 def news_amount_by_folder=(amount)
@@ -285,8 +288,9 @@ class Environment &lt; ActiveRecord::Base @@ -285,8 +288,9 @@ class Environment &lt; ActiveRecord::Base
285 end 288 end
286 289
287 # Enables a feature identified by its name 290 # Enables a feature identified by its name
288 - def enable(feature) 291 + def enable(feature, must_save=true)
289 self.settings["#{feature}_enabled".to_sym] = true 292 self.settings["#{feature}_enabled".to_sym] = true
  293 + self.save! if must_save
290 end 294 end
291 295
292 def enable_plugin(plugin) 296 def enable_plugin(plugin)
@@ -296,8 +300,9 @@ class Environment &lt; ActiveRecord::Base @@ -296,8 +300,9 @@ class Environment &lt; ActiveRecord::Base
296 end 300 end
297 301
298 # Disables a feature identified by its name 302 # Disables a feature identified by its name
299 - def disable(feature) 303 + def disable(feature, must_save=true)
300 self.settings["#{feature}_enabled".to_sym] = false 304 self.settings["#{feature}_enabled".to_sym] = false
  305 + self.save! if must_save
301 end 306 end
302 307
303 def disable_plugin(plugin) 308 def disable_plugin(plugin)
@@ -341,7 +346,7 @@ class Environment &lt; ActiveRecord::Base @@ -341,7 +346,7 @@ class Environment &lt; ActiveRecord::Base
341 %w( 346 %w(
342 disable_asset_products 347 disable_asset_products
343 disable_gender_icon 348 disable_gender_icon
344 - disable_products_for_enterprises 349 + products_for_enterprises
345 disable_select_city_for_contact 350 disable_select_city_for_contact
346 enterprise_registration 351 enterprise_registration
347 media_panel 352 media_panel
@@ -349,7 +354,7 @@ class Environment &lt; ActiveRecord::Base @@ -349,7 +354,7 @@ class Environment &lt; ActiveRecord::Base
349 show_balloon_with_profile_links_when_clicked 354 show_balloon_with_profile_links_when_clicked
350 use_portal_community 355 use_portal_community
351 ).each do |feature| 356 ).each do |feature|
352 - enable(feature) 357 + enable(feature, false)
353 end 358 end
354 end 359 end
355 360
@@ -802,13 +807,6 @@ class Environment &lt; ActiveRecord::Base @@ -802,13 +807,6 @@ class Environment &lt; ActiveRecord::Base
802 self.save! 807 self.save!
803 end 808 end
804 809
805 - after_destroy :destroy_templates  
806 - def destroy_templates  
807 - [enterprise_template, inactive_enterprise_template, community_template, person_template].compact.each do |template|  
808 - template.destroy  
809 - end  
810 - end  
811 -  
812 after_create :create_default_licenses 810 after_create :create_default_licenses
813 def create_default_licenses 811 def create_default_licenses
814 [ 812 [
app/models/event.rb
@@ -30,12 +30,30 @@ class Event &lt; Article @@ -30,12 +30,30 @@ class Event &lt; Article
30 30
31 validates_each :start_date do |event,field,value| 31 validates_each :start_date do |event,field,value|
32 if event.end_date && event.start_date && event.start_date > event.end_date 32 if event.end_date && event.start_date && event.start_date > event.end_date
33 - event.errors.add(:start_date, _('%{fn} cannot come before end date.').fix_i18n) 33 + event.errors.add(:start_date, _('{fn} cannot come before end date.').fix_i18n)
34 end 34 end
35 end 35 end
36 36
37 scope :by_day, lambda { |date| 37 scope :by_day, lambda { |date|
38 - {:conditions => ['start_date = :date AND end_date IS NULL OR (start_date <= :date AND end_date >= :date)', {:date => date}]} 38 + { :conditions => ['start_date = :date AND end_date IS NULL OR (start_date <= :date AND end_date >= :date)', {:date => date}],
  39 + :order => 'start_date ASC'
  40 + }
  41 + }
  42 +
  43 + scope :next_events_from_month, lambda { |date|
  44 + date_temp = date.strftime("%Y-%m-%d")
  45 + { :conditions => ["start_date >= ?","#{date_temp}"],
  46 + :limit => 10,
  47 + :order => 'start_date ASC'
  48 + }
  49 + }
  50 +
  51 + 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],
  54 + :limit => 10,
  55 + :order => 'start_date ASC'
  56 + }
39 } 57 }
40 58
41 include WhiteListFilter 59 include WhiteListFilter
@@ -112,7 +130,7 @@ class Event &lt; Article @@ -112,7 +130,7 @@ class Event &lt; Article
112 130
113 # TODO: some good soul, please clean this ugly hack: 131 # TODO: some good soul, please clean this ugly hack:
114 if self.body 132 if self.body
115 - html.div('_____XXXX_DESCRIPTION_GOES_HERE_XXXX_____', :class => 'event-description') 133 + html.div('_____XXXX_DESCRIPTION_GOES_HERE_XXXX_____', :class => 'event-description')
116 end 134 end
117 } 135 }
118 136
app/models/featured_products_block.rb
@@ -7,8 +7,9 @@ class FeaturedProductsBlock &lt; Block @@ -7,8 +7,9 @@ class FeaturedProductsBlock &lt; Block
7 7
8 before_save do |block| 8 before_save do |block|
9 if block.owner.kind_of?(Environment) && block.product_ids.blank? 9 if block.owner.kind_of?(Environment) && block.product_ids.blank?
10 - seed = block.owner.products.count  
11 - block.product_ids = block.owner.highlighted_products_with_image(:offset => (rand(seed) % (seed - block.groups_of * 3)), :limit => block.groups_of * 3).map(&:id) 10 + total = block.owner.products.count
  11 + offset = rand([(total - block.groups_of * 3) + 1, 1].max)
  12 + block.product_ids = block.owner.highlighted_products_with_image(:offset => offset, :limit => block.groups_of * 3).map(&:id)
12 end 13 end
13 block.groups_of = block.groups_of.to_i 14 block.groups_of = block.groups_of.to_i
14 end 15 end
app/models/image.rb
@@ -17,7 +17,7 @@ class Image &lt; ActiveRecord::Base @@ -17,7 +17,7 @@ class Image &lt; ActiveRecord::Base
17 :icon => '20x20!' }, 17 :icon => '20x20!' },
18 :max_size => 5.megabytes # remember to update validate message below 18 :max_size => 5.megabytes # remember to update validate message below
19 19
20 - validates_attachment :size => N_("%{fn} of uploaded file was larger than the maximum size of 5.0 MB").fix_i18n 20 + validates_attachment :size => N_("{fn} of uploaded file was larger than the maximum size of 5.0 MB").fix_i18n
21 21
22 delay_attachment_fu_thumbnails 22 delay_attachment_fu_thumbnails
23 23
app/models/link_list_block.rb
@@ -35,6 +35,12 @@ class LinkListBlock &lt; Block @@ -35,6 +35,12 @@ class LinkListBlock &lt; Block
35 ['chat', N_('Chat')] 35 ['chat', N_('Chat')]
36 ] 36 ]
37 37
  38 + TARGET_OPTIONS = [
  39 + [N_('Same page'), '_self'],
  40 + [N_('New tab'), '_blank'],
  41 + [N_('New window'), '_new'],
  42 + ]
  43 +
38 settings_items :links, Array, :default => [] 44 settings_items :links, Array, :default => []
39 45
40 before_save do |block| 46 before_save do |block|
@@ -59,7 +65,7 @@ class LinkListBlock &lt; Block @@ -59,7 +65,7 @@ class LinkListBlock &lt; Block
59 def link_html(link) 65 def link_html(link)
60 klass = 'icon-' + link[:icon] if link[:icon] 66 klass = 'icon-' + link[:icon] if link[:icon]
61 sanitize_link( 67 sanitize_link(
62 - link_to(link[:name], expand_address(link[:address]), :class => klass) 68 + link_to(link[:name], expand_address(link[:address]), :target => link[:target], :class => klass)
63 ) 69 )
64 end 70 end
65 71
app/models/person.rb
@@ -32,6 +32,10 @@ class Person &lt; Profile @@ -32,6 +32,10 @@ class Person &lt; Profile
32 Profile.memberships_of(self) 32 Profile.memberships_of(self)
33 end 33 end
34 34
  35 + def memberships_by_role(role)
  36 + memberships.where('role_assignments.role_id = ?', role.id)
  37 + end
  38 +
35 has_many :friendships, :dependent => :destroy 39 has_many :friendships, :dependent => :destroy
36 has_many :friends, :class_name => 'Person', :through => :friendships 40 has_many :friends, :class_name => 'Person', :through => :friendships
37 41
@@ -61,6 +65,10 @@ class Person &lt; Profile @@ -61,6 +65,10 @@ class Person &lt; Profile
61 scope :abusers, :joins => :abuse_complaints, :conditions => ['tasks.status = 3'], :select => 'DISTINCT profiles.*' 65 scope :abusers, :joins => :abuse_complaints, :conditions => ['tasks.status = 3'], :select => 'DISTINCT profiles.*'
62 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.*" 66 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.*"
63 67
  68 + scope :admins, :joins => [:role_assignments => :role], :conditions => ['roles.key = ?', 'environment_administrator' ]
  69 + scope :activated, :joins => :user, :conditions => ['users.activation_code IS NULL AND users.activated_at IS NOT NULL']
  70 + scope :deactivated, :joins => :user, :conditions => ['NOT (users.activation_code IS NULL AND users.activated_at IS NOT NULL)']
  71 +
64 after_destroy do |person| 72 after_destroy do |person|
65 Friendship.find(:all, :conditions => { :friend_id => person.id}).each { |friendship| friendship.destroy } 73 Friendship.find(:all, :conditions => { :friend_id => person.id}).each { |friendship| friendship.destroy }
66 end 74 end
@@ -230,7 +238,7 @@ class Person &lt; Profile @@ -230,7 +238,7 @@ class Person &lt; Profile
230 238
231 validates_each :email, :on => :update do |record,attr,value| 239 validates_each :email, :on => :update do |record,attr,value|
232 if User.find(:first, :conditions => ['email = ? and id != ? and environment_id = ?', value, record.user.id, record.environment.id]) 240 if User.find(:first, :conditions => ['email = ? and id != ? and environment_id = ?', value, record.user.id, record.environment.id])
233 - record.errors.add(attr, _('%{fn} is already used by other user').fix_i18n) 241 + record.errors.add(attr, _('{fn} is already used by other user').fix_i18n)
234 end 242 end
235 end 243 end
236 244
@@ -458,11 +466,19 @@ class Person &lt; Profile @@ -458,11 +466,19 @@ class Person &lt; Profile
458 end 466 end
459 467
460 def activities 468 def activities
461 - Scrap.find_by_sql("SELECT id, updated_at, '#{Scrap.to_s}' AS klass FROM #{Scrap.table_name} WHERE scraps.receiver_id = #{self.id} AND scraps.scrap_id IS NULL UNION SELECT id, updated_at, '#{ActionTracker::Record.to_s}' AS klass FROM #{ActionTracker::Record.table_name} WHERE action_tracker.user_id = #{self.id} and action_tracker.verb != 'leave_scrap_to_self' and action_tracker.verb != 'add_member_in_community' ORDER BY updated_at DESC") 469 + Scrap.find_by_sql("SELECT id, updated_at, '#{Scrap.to_s}' AS klass FROM #{Scrap.table_name} WHERE scraps.receiver_id = #{self.id} AND scraps.scrap_id IS NULL UNION SELECT id, updated_at, '#{ActionTracker::Record.to_s}' AS klass FROM #{ActionTracker::Record.table_name} WHERE action_tracker.user_id = #{self.id} and action_tracker.verb != 'leave_scrap_to_self' and action_tracker.verb != 'add_member_in_community' and action_tracker.verb != 'reply_scrap_on_self' ORDER BY updated_at DESC")
462 end 470 end
463 471
  472 + # by default, all fields are private
464 def public_fields 473 def public_fields
465 - self.fields_privacy.nil? ? self.active_fields : self.fields_privacy.reject{ |k, v| v != 'public' }.keys.map(&:to_s) 474 + self.fields_privacy.nil? ? [] : self.fields_privacy.reject{ |k, v| v != 'public' }.keys.map(&:to_s)
  475 + end
  476 +
  477 + include Noosfero::Gravatar
  478 +
  479 + def profile_custom_icon(gravatar_default=nil)
  480 + (self.image.present? && self.image.public_filename(:icon)) ||
  481 + gravatar_profile_image_url(self.email, :size=>20, :d => gravatar_default)
466 end 482 end
467 483
468 protected 484 protected
app/models/price_detail.rb
@@ -6,11 +6,11 @@ class PriceDetail &lt; ActiveRecord::Base @@ -6,11 +6,11 @@ class PriceDetail &lt; ActiveRecord::Base
6 validates_presence_of :product_id 6 validates_presence_of :product_id
7 7
8 belongs_to :production_cost 8 belongs_to :production_cost
9 - validates_presence_of :production_cost 9 + # Do not validates_presence_of production_cost. We may have undefined other costs.
10 validates_uniqueness_of :production_cost_id, :scope => :product_id 10 validates_uniqueness_of :production_cost_id, :scope => :product_id
11 11
12 def name 12 def name
13 - production_cost.name 13 + production_cost.nil? ? _('Other costs') : production_cost.name
14 end 14 end
15 15
16 def price 16 def price
app/models/product.rb
@@ -205,11 +205,13 @@ class Product &lt; ActiveRecord::Base @@ -205,11 +205,13 @@ class Product &lt; ActiveRecord::Base
205 (price - total_production_cost.to_f).zero? 205 (price - total_production_cost.to_f).zero?
206 end 206 end
207 207
208 - def update_price_details(price_details)  
209 - self.price_details.destroy_all  
210 - price_details.each do |price_detail|  
211 - self.price_details.create(price_detail) 208 + def update_price_details(new_price_details)
  209 + price_details.destroy_all
  210 + new_price_details.each do |detail|
  211 + price_details.create(detail)
212 end 212 end
  213 + reload # to remove temporary duplicated price_details
  214 + price_details
213 end 215 end
214 216
215 def price_description_percentage 217 def price_description_percentage
app/models/profile.rb
@@ -86,7 +86,8 @@ class Profile &lt; ActiveRecord::Base @@ -86,7 +86,8 @@ class Profile &lt; ActiveRecord::Base
86 #FIXME: these will work only if the subclass is already loaded 86 #FIXME: these will work only if the subclass is already loaded
87 scope :enterprises, lambda { {:conditions => (Enterprise.send(:subclasses).map(&:name) << 'Enterprise').map { |klass| "profiles.type = '#{klass}'"}.join(" OR ")} } 87 scope :enterprises, lambda { {:conditions => (Enterprise.send(:subclasses).map(&:name) << 'Enterprise').map { |klass| "profiles.type = '#{klass}'"}.join(" OR ")} }
88 scope :communities, lambda { {:conditions => (Community.send(:subclasses).map(&:name) << 'Community').map { |klass| "profiles.type = '#{klass}'"}.join(" OR ")} } 88 scope :communities, lambda { {:conditions => (Community.send(:subclasses).map(&:name) << 'Community').map { |klass| "profiles.type = '#{klass}'"}.join(" OR ")} }
89 - scope :templates, lambda { |environment| { :conditions => {:is_template => true, :environment_id => environment.id} } } 89 + scope :templates, {:conditions => {:is_template => true}}
  90 + scope :no_templates, {:conditions => {:is_template => false}}
90 91
91 def members 92 def members
92 scopes = plugins.dispatch_scopes(:organization_members, self) 93 scopes = plugins.dispatch_scopes(:organization_members, self)
@@ -98,6 +99,14 @@ class Profile &lt; ActiveRecord::Base @@ -98,6 +99,14 @@ class Profile &lt; ActiveRecord::Base
98 members.count 99 members.count
99 end 100 end
100 101
  102 + class << self
  103 + def count_with_distinct(*args)
  104 + options = args.last || {}
  105 + count_without_distinct(:id, {:distinct => true}.merge(options))
  106 + end
  107 + alias_method_chain :count, :distinct
  108 + end
  109 +
101 def members_by_role(role) 110 def members_by_role(role)
102 Person.members_of(self).all(:conditions => ['role_assignments.role_id = ?', role.id]) 111 Person.members_of(self).all(:conditions => ['role_assignments.role_id = ?', role.id])
103 end 112 end
@@ -111,6 +120,7 @@ class Profile &lt; ActiveRecord::Base @@ -111,6 +120,7 @@ class Profile &lt; ActiveRecord::Base
111 end 120 end
112 121
113 scope :visible, :conditions => { :visible => true } 122 scope :visible, :conditions => { :visible => true }
  123 + scope :public, :conditions => { :visible => true, :public_profile => true }
114 # Subclasses must override these methods 124 # Subclasses must override these methods
115 scope :more_popular 125 scope :more_popular
116 scope :more_active 126 scope :more_active
@@ -187,7 +197,7 @@ class Profile &lt; ActiveRecord::Base @@ -187,7 +197,7 @@ class Profile &lt; ActiveRecord::Base
187 197
188 has_many :tasks, :dependent => :destroy, :as => 'target' 198 has_many :tasks, :dependent => :destroy, :as => 'target'
189 199
190 - has_many :events, :source => 'articles', :class_name => 'Event', :order => 'name' 200 + has_many :events, :source => 'articles', :class_name => 'Event', :order => 'start_date'
191 201
192 def find_in_all_tasks(task_id) 202 def find_in_all_tasks(task_id)
193 begin 203 begin
@@ -220,12 +230,14 @@ class Profile &lt; ActiveRecord::Base @@ -220,12 +230,14 @@ class Profile &lt; ActiveRecord::Base
220 230
221 belongs_to :region 231 belongs_to :region
222 232
  233 + LOCATION_FIELDS = %w[address district city state country_name zip_code]
  234 +
223 def location(separator = ' - ') 235 def location(separator = ' - ')
224 myregion = self.region 236 myregion = self.region
225 if myregion 237 if myregion
226 myregion.hierarchy.reverse.first(2).map(&:name).join(separator) 238 myregion.hierarchy.reverse.first(2).map(&:name).join(separator)
227 else 239 else
228 - %w[address district city state country_name zip_code ].map {|item| (self.respond_to?(item) && !self.send(item).blank?) ? self.send(item) : nil }.compact.join(separator) 240 + LOCATION_FIELDS.map {|item| (self.respond_to?(item) && !self.send(item).blank?) ? self.send(item) : nil }.compact.join(separator)
229 end 241 end
230 end 242 end
231 243
@@ -292,7 +304,7 @@ class Profile &lt; ActiveRecord::Base @@ -292,7 +304,7 @@ class Profile &lt; ActiveRecord::Base
292 validate :valid_template 304 validate :valid_template
293 305
294 def valid_template 306 def valid_template
295 - if template_id.present? and !template.is_template 307 + if template_id.present? && template && !template.is_template
296 errors.add(:template, _('is not a template.')) 308 errors.add(:template, _('is not a template.'))
297 end 309 end
298 end 310 end
@@ -843,8 +855,10 @@ private :generate_url, :url_options @@ -843,8 +855,10 @@ private :generate_url, :url_options
843 }[amount] || _("%s members") % amount 855 }[amount] || _("%s members") % amount
844 end 856 end
845 857
846 - def profile_custom_icon  
847 - self.image.public_filename(:icon) unless self.image.blank? 858 + include Noosfero::Gravatar
  859 +
  860 + def profile_custom_icon(gravatar_default=nil)
  861 + image.public_filename(:icon) if image.present?
848 end 862 end
849 863
850 def jid(options = {}) 864 def jid(options = {})
@@ -883,6 +897,21 @@ private :generate_url, :url_options @@ -883,6 +897,21 @@ private :generate_url, :url_options
883 [] 897 []
884 end 898 end
885 899
  900 + def may_display_field_to? field, user = nil
  901 + if not self.active_fields.include? field.to_s
  902 + self.send "may_display_#{field}_to?", user rescue true
  903 + else
  904 + not (!self.public_fields.include? field.to_s and (!user or (user != self and !user.is_a_friend?(self))))
  905 + end
  906 + end
  907 +
  908 + def may_display_location_to? user = nil
  909 + LOCATION_FIELDS.each do |field|
  910 + return false if !self.may_display_field_to? field, user
  911 + end
  912 + return true
  913 + end
  914 +
886 # field => privacy (e.g.: "address" => "public") 915 # field => privacy (e.g.: "address" => "public")
887 def fields_privacy 916 def fields_privacy
888 self.data[:fields_privacy] 917 self.data[:fields_privacy]
app/models/profile_list_block.rb
@@ -56,7 +56,7 @@ class ProfileListBlock &lt; Block @@ -56,7 +56,7 @@ class ProfileListBlock &lt; Block
56 list = content_tag 'ul', nl +' '+ list + nl 56 list = content_tag 'ul', nl +' '+ list + nl
57 end 57 end
58 block_title(title) + nl + 58 block_title(title) + nl +
59 - content_tag('div', nl + list + nl + content_tag('br', '', :style => 'clear:both')) 59 + content_tag('div', nl + list + nl + tag('br', :style => 'clear:both'))
60 end 60 end
61 end 61 end
62 62
app/models/raw_html_block.rb
@@ -12,4 +12,7 @@ class RawHTMLBlock &lt; Block @@ -12,4 +12,7 @@ class RawHTMLBlock &lt; Block
12 (title.blank? ? '' : block_title(title)).html_safe + html.to_s.html_safe 12 (title.blank? ? '' : block_title(title)).html_safe + html.to_s.html_safe
13 end 13 end
14 14
  15 + def has_macro?
  16 + true
  17 + end
15 end 18 end
app/models/recent_documents_block.rb
@@ -32,8 +32,7 @@ class RecentDocumentsBlock &lt; Block @@ -32,8 +32,7 @@ class RecentDocumentsBlock &lt; Block
32 end 32 end
33 end 33 end
34 34
35 - def docs  
36 - self.limit.nil? ? owner.recent_documents(nil, {}, false) : owner.recent_documents(self.limit, {}, false) 35 + def self.expire_on
  36 + { :profile => [:article], :environment => [:article] }
37 end 37 end
38 -  
39 end 38 end
app/models/region.rb
@@ -11,9 +11,9 @@ class Region &lt; Category @@ -11,9 +11,9 @@ class Region &lt; Category
11 validators.count > 0 11 validators.count > 0
12 end 12 end
13 13
14 - scope :with_validators, :group => 'id', 14 + scope :with_validators, :select => 'DISTINCT ON (categories.id) *',
15 :joins => 'INNER JOIN region_validators on (region_validators.region_id = categories.id)' 15 :joins => 'INNER JOIN region_validators on (region_validators.region_id = categories.id)'
16 - 16 +
17 end 17 end
18 18
19 require_dependency 'city' 19 require_dependency 'city'
app/models/scrap.rb
@@ -17,9 +17,11 @@ class Scrap &lt; ActiveRecord::Base @@ -17,9 +17,11 @@ 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.receiver != s.sender}, :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.receiver == s.sender} 22 + track_actions :leave_scrap_to_self, :after_create, :keep_params => ['sender.name', 'content'], :if => Proc.new{|s| s.sender == s.receiver}
  23 +
  24 + track_actions :reply_scrap_on_self, :after_create, :keep_params => ['sender.name', 'content'], :if => Proc.new{|s| s.sender != s.receiver && s.sender == s.top_root.receiver}
23 25
24 after_create do |scrap| 26 after_create do |scrap|
25 scrap.root.update_attribute('updated_at', DateTime.now) unless scrap.root.nil? 27 scrap.root.update_attribute('updated_at', DateTime.now) unless scrap.root.nil?
@@ -28,6 +30,12 @@ class Scrap &lt; ActiveRecord::Base @@ -28,6 +30,12 @@ class Scrap &lt; ActiveRecord::Base
28 30
29 before_validation :strip_all_html_tags 31 before_validation :strip_all_html_tags
30 32
  33 + def top_root
  34 + scrap = self
  35 + scrap = Scrap.find(scrap.scrap_id) while scrap.scrap_id
  36 + scrap
  37 + end
  38 +
31 def strip_all_html_tags 39 def strip_all_html_tags
32 sanitizer = HTML::WhiteListSanitizer.new 40 sanitizer = HTML::WhiteListSanitizer.new
33 self.content = sanitizer.sanitize(self.content, :tags => []) 41 self.content = sanitizer.sanitize(self.content, :tags => [])
app/models/spammer_logger.rb
@@ -6,6 +6,8 @@ class SpammerLogger &lt; Logger @@ -6,6 +6,8 @@ class SpammerLogger &lt; Logger
6 if object 6 if object
7 if object.kind_of?(Comment) 7 if object.kind_of?(Comment)
8 @logger << "[#{Time.now.strftime('%F %T %z')}] Comment-id: #{object.id} IP: #{spammer_ip}\n" 8 @logger << "[#{Time.now.strftime('%F %T %z')}] Comment-id: #{object.id} IP: #{spammer_ip}\n"
  9 + elsif object.kind_of?(SuggestArticle)
  10 + @logger << "[#{Time.now.strftime('%F %T %z')}] SuggestArticle-id: #{object.id} IP: #{spammer_ip}\n"
9 end 11 end
10 else 12 else
11 @logger << "[#{Time.now.strftime('%F %T %z')}] IP: #{spammer_ip}\n" 13 @logger << "[#{Time.now.strftime('%F %T %z')}] IP: #{spammer_ip}\n"
app/models/suggest_article.rb
@@ -11,6 +11,17 @@ class SuggestArticle &lt; Task @@ -11,6 +11,17 @@ class SuggestArticle &lt; Task
11 settings_items :source, :type => String 11 settings_items :source, :type => String
12 settings_items :source_name, :type => String 12 settings_items :source_name, :type => String
13 settings_items :highlighted, :type => :boolean, :default => false 13 settings_items :highlighted, :type => :boolean, :default => false
  14 + settings_items :ip_address, :type => String
  15 + settings_items :user_agent, :type => String
  16 + settings_items :referrer, :type => String
  17 +
  18 + after_create :schedule_spam_checking
  19 +
  20 + def schedule_spam_checking
  21 + self.delay.check_for_spam
  22 + end
  23 +
  24 + include Noosfero::Plugin::HotSpot
14 25
15 def sender 26 def sender
16 "#{name} (#{email})" 27 "#{name} (#{email})"
@@ -61,4 +72,12 @@ class SuggestArticle &lt; Task @@ -61,4 +72,12 @@ class SuggestArticle &lt; Task
61 _('You need to login on %{system} in order to approve or reject this article.') % { :system => target.environment.name } 72 _('You need to login on %{system} in order to approve or reject this article.') % { :system => target.environment.name }
62 end 73 end
63 74
  75 + def after_spam!
  76 + SpammerLogger.log(ip_address, self)
  77 + self.delay.marked_as_spam
  78 + end
  79 +
  80 + def after_ham!
  81 + self.delay.marked_as_ham
  82 + end
64 end 83 end
app/models/tags_block.rb
@@ -59,4 +59,8 @@ class TagsBlock &lt; Block @@ -59,4 +59,8 @@ class TagsBlock &lt; Block
59 15.minutes 59 15.minutes
60 end 60 end
61 61
  62 + def self.expire_on
  63 + { :profile => [:article], :environment => [:article] }
  64 + end
  65 +
62 end 66 end
app/models/task.rb
@@ -258,6 +258,8 @@ class Task &lt; ActiveRecord::Base @@ -258,6 +258,8 @@ class Task &lt; ActiveRecord::Base
258 status == Task::Status::ACTIVE || status == Task::Status::HIDDEN 258 status == Task::Status::ACTIVE || status == Task::Status::HIDDEN
259 end 259 end
260 260
  261 + include Spammable
  262 +
261 protected 263 protected
262 264
263 # This method must be overrided in subclasses, and its implementation must do 265 # This method must be overrided in subclasses, and its implementation must do
app/models/uploaded_file.rb
@@ -45,7 +45,25 @@ class UploadedFile &lt; Article @@ -45,7 +45,25 @@ class UploadedFile &lt; Article
45 end 45 end
46 46
47 def self.max_size 47 def self.max_size
48 - UploadedFile.attachment_options[:max_size] 48 + default = 5.megabytes
  49 +
  50 + multipliers = {
  51 + :KB => :kilobytes,
  52 + :MB => :megabytes,
  53 + :GB => :gigabytes,
  54 + :TB => :terabytes,
  55 + }
  56 + max_upload_size = NOOSFERO_CONF['max_upload_size']
  57 +
  58 + if max_upload_size =~ /^(\d+(\.\d+)?)\s*(KB|MB|GB|TB)?$/
  59 + number = $1.to_f
  60 + unit = $3 || :MB
  61 + multiplier = multipliers[unit.to_sym]
  62 +
  63 + number.send(multiplier).to_i
  64 + else
  65 + default
  66 + end
49 end 67 end
50 68
51 # FIXME need to define min/max file size 69 # FIXME need to define min/max file size
@@ -56,20 +74,28 @@ class UploadedFile &lt; Article @@ -56,20 +74,28 @@ class UploadedFile &lt; Article
56 has_attachment :storage => :file_system, 74 has_attachment :storage => :file_system,
57 :thumbnails => { :icon => [24,24], :thumb => '130x130>', :slideshow => '320x240>', :display => '640X480>' }, 75 :thumbnails => { :icon => [24,24], :thumb => '130x130>', :slideshow => '320x240>', :display => '640X480>' },
58 :thumbnail_class => Thumbnail, 76 :thumbnail_class => Thumbnail,
59 - :max_size => 5.megabytes # remember to update validate message below 77 + :max_size => self.max_size
60 78
61 - validates_attachment :size => N_("%{fn} of uploaded file was larger than the maximum size of 5.0 MB").fix_i18n 79 + validates_attachment :size => N_("{fn} of uploaded file was larger than the maximum size of %{size}").sub('%{size}', self.max_size.to_humanreadable).fix_i18n
62 80
63 delay_attachment_fu_thumbnails 81 delay_attachment_fu_thumbnails
64 82
65 postgresql_attachment_fu 83 postgresql_attachment_fu
66 84
  85 + # Use this method only to get the generic icon for this kind of content.
  86 + # If you want the specific icon for a file type or the iconified version
  87 + # of an image, use FilePresenter.for(uploaded_file).icon_name
67 def self.icon_name(article = nil) 88 def self.icon_name(article = nil)
68 - if article  
69 - article.image? ? article.public_filename(:icon) : (article.mime_type ? article.mime_type.gsub(/[\/+.]/, '-') : 'upload-file')  
70 - else  
71 - 'upload-file' 89 + unless article.nil?
  90 + warn = ('='*80) + "\n" +
  91 + 'The method `UploadedFile.icon_name(obj)` is deprecated. ' +
  92 + 'You must to encapsulate UploadedFile with `FilePresenter.for()`.' +
  93 + "\n" + ('='*80)
  94 + raise NoMethodError, warn if ENV['RAILS_ENV'] == 'test'
  95 + Rails.logger.warn warn if Rails.logger
  96 + puts warn if ENV['RAILS_ENV'] == 'development'
72 end 97 end
  98 + 'upload-file'
73 end 99 end
74 100
75 def mime_type 101 def mime_type
@@ -90,45 +116,38 @@ class UploadedFile &lt; Article @@ -90,45 +116,38 @@ class UploadedFile &lt; Article
90 self.name = self.filename 116 self.name = self.filename
91 end 117 end
92 118
  119 + def download_headers
  120 + {
  121 + 'Content-Disposition' => "attachment; filename=\"#{self.filename}\"",
  122 + }
  123 + end
  124 +
93 def data 125 def data
94 File.read(self.full_filename) 126 File.read(self.full_filename)
95 end 127 end
96 128
97 def to_html(options = {}) 129 def to_html(options = {})
  130 + warn = ('='*80) + "\n" +
  131 + 'The method `UploadedFile#to_html()` is deprecated. ' +
  132 + 'You must to encapsulate UploadedFile with `FilePresenter.for()`.' +
  133 + "\n" + ('='*80)
  134 + raise NoMethodError, warn if ENV['RAILS_ENV'] == 'test'
  135 + Rails.logger.warn warn if Rails.logger
  136 + puts warn if ENV['RAILS_ENV'] == 'development'
98 article = self 137 article = self
99 if image? 138 if image?
100 proc do 139 proc do
101 - if article.gallery? && options[:gallery_view]  
102 - images = article.parent.images  
103 - current_index = images.index(article)  
104 - total_of_images = images.count  
105 -  
106 - link_to_previous = if current_index >= 1  
107 - link_to(_('&laquo; Previous'), images[current_index - 1].view_url, :class => 'left')  
108 - else  
109 - content_tag('span', _('&laquo; Previous'), :class => 'left')  
110 - end  
111 -  
112 - link_to_next = if current_index < total_of_images - 1  
113 - link_to(_('Next &raquo;'), images[current_index + 1].view_url, :class => 'right')  
114 - else  
115 - content_tag('span', _('Next &raquo;'), :class => 'right')  
116 - end  
117 -  
118 - content_tag(  
119 - 'div',  
120 - link_to_previous + (content_tag('span', _('image %d of %d'), :class => 'total-of-images') % [current_index + 1, total_of_images]).html_safe + link_to_next,  
121 - :class => 'gallery-navigation'  
122 - )  
123 - end.to_s +  
124 - image_tag(article.public_filename(:display), :class => article.css_class_name, :style => 'max-width: 100%') +  
125 - content_tag('p', article.abstract, :class => 'uploaded-file-description')  
126 - 140 + image_tag(article.public_filename(:display),
  141 + :class => article.css_class_name,
  142 + :style => 'max-width: 100%') +
  143 + content_tag('div', article.abstract, :class => 'uploaded-file-description')
127 end 144 end
128 else 145 else
129 proc do 146 proc do
130 - content_tag('ul', content_tag('li', link_to(article.name, article.url, :class => article.css_class_name))) +  
131 - content_tag('p', article.abstract, :class => 'uploaded-file-description') 147 + content_tag('div',
  148 + link_to(article.name, article.url),
  149 + :class => article.css_class_name) +
  150 + content_tag('div', article.abstract, :class => 'uploaded-file-description')
132 end 151 end
133 end 152 end
134 end 153 end
app/models/user.rb
@@ -89,7 +89,7 @@ class User &lt; ActiveRecord::Base @@ -89,7 +89,7 @@ class User &lt; ActiveRecord::Base
89 before_save :encrypt_password 89 before_save :encrypt_password
90 validates_format_of :email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => (lambda {|user| !user.email.blank?}) 90 validates_format_of :email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => (lambda {|user| !user.email.blank?})
91 91
92 - validates_inclusion_of :terms_accepted, :in => [ '1' ], :if => lambda { |u| ! u.terms_of_use.blank? }, :message => N_('%{fn} must be checked in order to signup.').fix_i18n 92 + validates_inclusion_of :terms_accepted, :in => [ '1' ], :if => lambda { |u| ! u.terms_of_use.blank? }, :message => N_('{fn} must be checked in order to signup.').fix_i18n
93 93
94 # Authenticates a user by their login name or email and unencrypted password. Returns the user or nil. 94 # Authenticates a user by their login name or email and unencrypted password. Returns the user or nil.
95 def self.authenticate(login, password, environment = nil) 95 def self.authenticate(login, password, environment = nil)
@@ -118,6 +118,21 @@ class User &lt; ActiveRecord::Base @@ -118,6 +118,21 @@ class User &lt; ActiveRecord::Base
118 end 118 end
119 end 119 end
120 120
  121 + # Deactivates the user in the database.
  122 + def deactivate
  123 + return false unless self.person
  124 + self.activated_at = nil
  125 + self.person.visible = false
  126 + begin
  127 + self.person.save! && self.save!
  128 + rescue Exception => exception
  129 + logger.error(exception.to_s)
  130 + false
  131 + else
  132 + true
  133 + end
  134 + end
  135 +
121 def activated? 136 def activated?
122 self.activation_code.nil? && !self.activated_at.nil? 137 self.activation_code.nil? && !self.activated_at.nil?
123 end 138 end
@@ -250,19 +265,21 @@ class User &lt; ActiveRecord::Base @@ -250,19 +265,21 @@ class User &lt; ActiveRecord::Base
250 end 265 end
251 end 266 end
252 267
253 - def data_hash 268 + def data_hash(gravatar_default = nil)
254 friends_list = {} 269 friends_list = {}
255 enterprises = person.enterprises.map { |e| { 'name' => e.short_name, 'identifier' => e.identifier } } 270 enterprises = person.enterprises.map { |e| { 'name' => e.short_name, 'identifier' => e.identifier } }
256 self.person.friends.online.map do |person| 271 self.person.friends.online.map do |person|
257 friends_list[person.identifier] = { 272 friends_list[person.identifier] = {
258 - 'avatar' => person.profile_custom_icon, 273 + 'avatar' => person.profile_custom_icon(gravatar_default),
259 'name' => person.short_name, 274 'name' => person.short_name,
260 'jid' => person.full_jid, 275 'jid' => person.full_jid,
261 'status' => person.user.chat_status, 276 'status' => person.user.chat_status,
262 } 277 }
263 end 278 end
  279 +
264 { 280 {
265 'login' => self.login, 281 'login' => self.login,
  282 + 'avatar' => self.person.profile_custom_icon(gravatar_default),
266 'is_admin' => self.person.is_admin?, 283 'is_admin' => self.person.is_admin?,
267 'since_month' => self.person.created_at.month, 284 'since_month' => self.person.created_at.month,
268 'since_year' => self.person.created_at.year, 285 'since_year' => self.person.created_at.year,
app/presenters/generic.rb 0 → 100644
@@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
  1 +# Made to encapsulate any UploadedFile
  2 +class FilePresenter::Generic < FilePresenter
  3 + # if returns low priority, because it is generic.
  4 + def self.accepts?(f)
  5 + 1 if f.is_a? UploadedFile
  6 + end
  7 +end
app/presenters/image.rb 0 → 100644
@@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
  1 +class FilePresenter::Image < FilePresenter
  2 + def self.accepts?(f)
  3 + return nil unless f.respond_to? :image?
  4 + f.image? ? 10 : nil
  5 + end
  6 +
  7 + def icon_name
  8 + public_filename :icon
  9 + end
  10 +
  11 + def short_description
  12 + _('Image (%s)') % content_type.split('/')[1].upcase
  13 + end
  14 +end
app/sweepers/article_sweeper.rb
@@ -16,15 +16,15 @@ class ArticleSweeper &lt; ActiveRecord::Observer @@ -16,15 +16,15 @@ class ArticleSweeper &lt; ActiveRecord::Observer
16 end 16 end
17 end 17 end
18 18
  19 +
19 protected 20 protected
20 21
21 def expire_caches(article) 22 def expire_caches(article)
  23 + expire_blocks_cache(article.profile, [:article])
  24 +
22 return if !article.environment 25 return if !article.environment
  26 +
23 article.hierarchy(true).each { |a| a.touch if a != article } 27 article.hierarchy(true).each { |a| a.touch if a != article }
24 - blocks = article.profile.blocks  
25 - blocks += article.profile.environment.blocks if article.profile.environment  
26 - blocks = blocks.select{|b|[RecentDocumentsBlock, BlogArchivesBlock].any?{|c| b.kind_of?(c)}}  
27 - BlockSweeper.expire_blocks(blocks)  
28 env = article.profile.environment 28 env = article.profile.environment
29 if env && (env.portal_community == article.profile) 29 if env && (env.portal_community == article.profile)
30 article.environment.locales.keys.each do |locale| 30 article.environment.locales.keys.each do |locale|
app/sweepers/category_sweeper.rb
@@ -3,7 +3,13 @@ class CategorySweeper &lt; ActiveRecord::Observer @@ -3,7 +3,13 @@ class CategorySweeper &lt; ActiveRecord::Observer
3 include SweeperHelper 3 include SweeperHelper
4 4
5 def after_save(category) 5 def after_save(category)
  6 + expire_blocks_cache(category.environment, [:category])
  7 +
  8 + # Needed for environments with application layout
6 expire_fragment(category.environment.id.to_s + "_categories_menu") 9 expire_fragment(category.environment.id.to_s + "_categories_menu")
7 end 10 end
8 11
  12 + def after_destroy(category)
  13 + expire_blocks_cache(category.environment, [:category])
  14 + end
9 end 15 end
app/sweepers/profile_sweeper.rb
@@ -4,7 +4,7 @@ class ProfileSweeper # &lt; ActiveRecord::Observer @@ -4,7 +4,7 @@ class ProfileSweeper # &lt; ActiveRecord::Observer
4 include SweeperHelper 4 include SweeperHelper
5 5
6 def after_update(profile) 6 def after_update(profile)
7 - expire_caches(profile) 7 + self.delay.expire_caches profile
8 end 8 end
9 9
10 def after_create(profile) 10 def after_create(profile)
app/views/account/_signup_form.html.erb
@@ -101,7 +101,7 @@ @@ -101,7 +101,7 @@
101 101
102 <%= @plugins.dispatch(:signup_extra_contents).collect { |content| instance_eval(&content) }.join("") %> 102 <%= @plugins.dispatch(:signup_extra_contents).collect { |content| instance_eval(&content) }.join("") %>
103 103
104 - <%= template_options(Person, 'profile_data') %> 104 + <%= template_options(:people, 'profile_data') %>
105 105
106 <% unless @terms_of_use.blank? %> 106 <% unless @terms_of_use.blank? %>
107 <div id='terms-of-use-box' class='formfieldline'> 107 <div id='terms-of-use-box' class='formfieldline'>
app/views/account/forgot_password.html.erb
@@ -2,21 +2,13 @@ @@ -2,21 +2,13 @@
2 2
3 <%= error_messages_for :change_password, :header_message => _('Instructions to password recovery could not be sent'), :message => nil %> 3 <%= error_messages_for :change_password, :header_message => _('Instructions to password recovery could not be sent'), :message => nil %>
4 4
5 -<%= labelled_form_for :change_password, @change_password, :url => { :action => 'forgot_password' } do |f| %>  
6 -  
7 - <%= f.text_field :login,  
8 - :onchange => 'this.value = convToValidUsername( this.value )' %>  
9 -  
10 - <%= f.text_field :email %>  
11 -  
12 - <%= f.hidden_field :environment_id, :value => environment.id %>  
13 -  
14 -<div>  
15 - <% button_bar do %>  
16 - <%= submit_button('send', _('Send instructions')) %>  
17 - <% end %>  
18 -</div>  
19 -<%= content_tag(:small,_('After clicking the button above, you will receive an email with a link to a page where you will be able to create a new password.')) %>  
20 - 5 +<% form_tag do %>
  6 + <%= labelled_form_field fields_label, text_field_tag(:value) %>
  7 +
  8 + <div>
  9 + <% button_bar do %>
  10 + <%= submit_button('send', _('Send instructions')) %>
  11 + <% end %>
  12 + </div>
  13 + <%= content_tag(:small,_('After clicking the button above, you will receive an email with a link to a page where you will be able to create a new password.')) %>
21 <% end %> 14 <% end %>
22 -  
app/views/blocks/location.html.erb
1 <% if profile.lat %> 1 <% if profile.lat %>
2 <%= block_title block.title %> 2 <%= block_title block.title %>
3 <div class='the-localization-map'> 3 <div class='the-localization-map'>
4 - <img src="http://maps.google.com/maps/api/staticmap?center=<%=profile.lat%>,<%=profile.lng%>&zoom=<%=block.zoom%>&size=190x250&maptype=<%=block.map_type%>&markers=<%=profile.lat%>,<%=profile.lng%>&sensor=false"/> 4 + <img src="https://maps.google.com/maps/api/staticmap?center=<%=profile.lat%>,<%=profile.lng%>&zoom=<%=block.zoom%>&size=190x250&maptype=<%=block.map_type%>&markers=<%=profile.lat%>,<%=profile.lng%>&sensor=false"/>
5 </div> 5 </div>
6 </div> 6 </div>
7 <% else %> 7 <% else %>
app/views/blocks/profile_info.html.erb
@@ -17,7 +17,7 @@ @@ -17,7 +17,7 @@
17 <ul class="profile-info-data" id="profile-info-data-<%= block.id %>"> 17 <ul class="profile-info-data" id="profile-info-data-<%= block.id %>">
18 <li><%= link_to _('Homepage'), block.owner.url, :class => 'url' %></li> 18 <li><%= link_to _('Homepage'), block.owner.url, :class => 'url' %></li>
19 <li><%= link_to _('View profile'), block.owner.public_profile_url %></li> 19 <li><%= link_to _('View profile'), block.owner.public_profile_url %></li>
20 - <% if block.owner.enterprise? && !block.owner.environment.enabled?('disable_products_for_enterprises') %> 20 + <% if block.owner.enterprise? && block.owner.environment.enabled?('products_for_enterprises') %>
21 <li><%= link_to(_('Products/Services'), :controller => 'catalog', :profile => block.owner.identifier) %></li> 21 <li><%= link_to(_('Products/Services'), :controller => 'catalog', :profile => block.owner.identifier) %></li>
22 <% end %> 22 <% end %>
23 <li id="profile-admin-url-<%= block.id %>"></li> 23 <li id="profile-admin-url-<%= block.id %>"></li>
app/views/box_organizer/_article_block.html.erb
1 <div class="article-block-edition"> 1 <div class="article-block-edition">
2 -<% if @block.box.owner.kind_of?(Environment) and @block.box.owner.portal_community.nil? %> 2 +<% if @block.owner.kind_of?(Environment) and @block.owner.portal_community.nil? %>
3 <p id="no_portal_community"> 3 <p id="no_portal_community">
4 <%= _("You don't have an community defined as the portal community. Define it before use this block properly.") %> 4 <%= _("You don't have an community defined as the portal community. Define it before use this block properly.") %>
5 </p> 5 </p>
app/views/box_organizer/_link_list_block.html.erb
1 <strong><%= _('Links') %></strong> 1 <strong><%= _('Links') %></strong>
2 <div id='edit-link-list-block' style='width:450px'> 2 <div id='edit-link-list-block' style='width:450px'>
3 <table id='links' class='noborder'> 3 <table id='links' class='noborder'>
4 - <tr><th><%= _('Icon') %></th><th><%= _('Name') %></th><th><%= _('Address') %></th></tr> 4 + <tr><th><%= _('Icon') %></th><th><%= _('Name') %></th><th><%= _('Address') %></th><th><%= _('Target') %></th></tr>
5 <% for link in @block.links do %> 5 <% for link in @block.links do %>
6 <tr> 6 <tr>
7 <td> 7 <td>
@@ -9,6 +9,9 @@ @@ -9,6 +9,9 @@
9 </td> 9 </td>
10 <td><%= text_field_tag 'block[links][][name]', link[:name], :class => 'link-name', :maxlength => 20 %></td> 10 <td><%= text_field_tag 'block[links][][name]', link[:name], :class => 'link-name', :maxlength => 20 %></td>
11 <td class='cel-address'><%= text_field_tag 'block[links][][address]', link[:address], :class => 'link-address' %></td> 11 <td class='cel-address'><%= text_field_tag 'block[links][][address]', link[:address], :class => 'link-address' %></td>
  12 + <td>
  13 + <%= select_tag('block[links][][target]', options_for_select(LinkListBlock::TARGET_OPTIONS, link[:target])) %>
  14 + </td>
12 </tr> 15 </tr>
13 <% end %> 16 <% end %>
14 </table> 17 </table>
@@ -18,7 +21,9 @@ @@ -18,7 +21,9 @@
18 page.insert_html :bottom, 'links', content_tag('tr', 21 page.insert_html :bottom, 'links', content_tag('tr',
19 content_tag('td', icon_selector('ok')) + 22 content_tag('td', icon_selector('ok')) +
20 content_tag('td', text_field_tag('block[links][][name]', '', :maxlength => 20)) + 23 content_tag('td', text_field_tag('block[links][][name]', '', :maxlength => 20)) +
21 - content_tag('td', text_field_tag('block[links][][address]', nil, :class => 'cel-address')) 24 + content_tag('td', text_field_tag('block[links][][address]', nil, :class => 'link-address'), :class => 'cel-address') +
  25 + content_tag('td', select_tag('block[links][][target]',
  26 +options_for_select(LinkListBlock::TARGET_OPTIONS, link[:target])))
22 ) + 27 ) +
23 javascript_tag("$('edit-link-list-block').scrollTop = $('edit-link-list-block').scrollHeight") 28 javascript_tag("$('edit-link-list-block').scrollTop = $('edit-link-list-block').scrollHeight")
24 end %> 29 end %>
app/views/catalog/index.html.erb
@@ -92,7 +92,7 @@ @@ -92,7 +92,7 @@
92 <% end %> 92 <% end %>
93 <% product.price_details.each do |i| %> 93 <% product.price_details.each do |i| %>
94 <div class="search-product-input-dots-to-price"> 94 <div class="search-product-input-dots-to-price">
95 - <div class="search-product-input-name"><%= i.production_cost.name %></div> 95 + <div class="search-product-input-name"><%= i.name %></div>
96 <%= price_span i.price, :class => 'search-product-input-price' %> 96 <%= price_span i.price, :class => 'search-product-input-price' %>
97 </div> 97 </div>
98 <% end %> 98 <% end %>
app/views/cms/_blog.html.erb
@@ -54,6 +54,15 @@ @@ -54,6 +54,15 @@
54 54
55 <%= labelled_form_field(_('Description:'), text_area(:article, :body, :rows => 10)) %> 55 <%= labelled_form_field(_('Description:'), text_area(:article, :body, :rows => 10)) %>
56 56
  57 +<% f.fields_for :image_builder, @article.image do |i| %>
  58 + <%= file_field_or_thumbnail(_('Cover image:'), @article.image, i)%>
  59 + <%= _("Max size: %s (.jpg, .gif, .png)")% Image.max_size.to_humanreadable %>
  60 +<% end %>
  61 +
  62 +<% unless @article.image.nil? %>
  63 + <%= labelled_check_box(_('Remove cover image'),'remove_image',true,false)%>
  64 +<% end %>
  65 +
57 <%= labelled_form_field(_('How to display posts:'), f.select(:visualization_format, [ [ _('Full post'), 'full'], [ _('First paragraph'), 'short'] ])) %> 66 <%= labelled_form_field(_('How to display posts:'), f.select(:visualization_format, [ [ _('Full post'), 'full'], [ _('First paragraph'), 'short'] ])) %>
58 67
59 <%= labelled_form_field(_('Posts per page:'), f.select(:posts_per_page, Blog.posts_per_page_options)) %> 68 <%= labelled_form_field(_('Posts per page:'), f.select(:posts_per_page, Blog.posts_per_page_options)) %>
app/views/cms/view.html.erb
@@ -2,6 +2,18 @@ @@ -2,6 +2,18 @@
2 <%= _('Content management') %> 2 <%= _('Content management') %>
3 </h1> 3 </h1>
4 4
  5 +<% if !environment.enabled?('cant_change_homepage') && !remove_content_button(:home) %>
  6 + <div class="cms-homepage">
  7 + <%= _('Profile homepage:') %>
  8 + <% if profile.home_page %>
  9 + <%= link_to_article(profile.home_page) %>
  10 + <%= button_without_text(:'home-not', _('Reset homepage'), { :action => 'set_home_page', :id => nil }, :method => :post) %>
  11 + <% else %>
  12 + <span class="cms-homepage-default"><%= _('Profile Information') %></span>
  13 + <% end %>
  14 + </div>
  15 +<% end %>
  16 +
5 <% button_bar(:style => 'margin-bottom: 1em;') do %> 17 <% button_bar(:style => 'margin-bottom: 1em;') do %>
6 <% parent_id = ((@article && @article.allow_children?) ? @article : nil) %> 18 <% parent_id = ((@article && @article.allow_children?) ? @article : nil) %>
7 19
@@ -40,20 +52,27 @@ @@ -40,20 +52,27 @@
40 </tr> 52 </tr>
41 <% end %> 53 <% end %>
42 54
43 - <% @articles.each do |article| %>  
44 - <tr>  
45 - <td> 55 + <% @articles.each do |article| article = FilePresenter.for article %>
  56 + <tr title="<%= article.title%>" >
  57 + <td class="article-name">
46 <%= link_to_article(article) %> 58 <%= link_to_article(article) %>
47 </td> 59 </td>
48 - <td>  
49 - <%= article.class.short_description %> 60 + <% short_description = article.respond_to?(:short_description) ?
  61 + article.short_description :
  62 + article.class.short_description %>
  63 + <td class="article-mime" title=<%= short_description.to_json %>>
  64 + <%= short_description %>
50 </td> 65 </td>
51 <td class="article-controls"> 66 <td class="article-controls">
52 <%= expirable_button article, :edit, _('Edit'), {:action => 'edit', :id => article.id} if !remove_content_button(:edit) %> 67 <%= expirable_button article, :edit, _('Edit'), {:action => 'edit', :id => article.id} if !remove_content_button(:edit) %>
53 <%= button_without_text :eyes, _('Public view'), article.view_url %> 68 <%= button_without_text :eyes, _('Public view'), article.view_url %>
54 <%= display_spread_button(profile, article) unless article.folder? || remove_content_button(:spread)%> 69 <%= display_spread_button(profile, article) unless article.folder? || remove_content_button(:spread)%>
55 <% if !environment.enabled?('cant_change_homepage') && !remove_content_button(:home) %> 70 <% if !environment.enabled?('cant_change_homepage') && !remove_content_button(:home) %>
56 - <%= expirable_button article, :home, _('Use as homepage'), { :action => 'set_home_page', :id => article.id }, :method => :post %> 71 + <% if profile.home_page != article %>
  72 + <%= expirable_button article, :home, _('Use as homepage'), { :action => 'set_home_page', :id => article.id }, :method => :post %>
  73 + <% else %>
  74 + <%= button_without_text(:'home-not', _('Reset homepage'), { :action => 'set_home_page', :id => nil }, :method => :post) %>
  75 + <% end %>
57 <% end %> 76 <% end %>
58 <%= display_delete_button(article) if !remove_content_button(:delete) %> 77 <%= display_delete_button(article) if !remove_content_button(:delete) %>
59 </td> 78 </td>
app/views/comment/_comment.rhtml
@@ -13,11 +13,11 @@ @@ -13,11 +13,11 @@
13 <% else %> 13 <% else %>
14 <% url_image, status_class = comment.author_id ? 14 <% url_image, status_class = comment.author_id ?
15 [comment.removed_user_image, 'icon-user-removed'] : 15 [comment.removed_user_image, 'icon-user-removed'] :
16 - [str_gravatar_url_for( comment.email, :size => 50, :d=>404 ), 'icon-user-unknown'] %> 16 + [gravatar_profile_image_url( comment.email, :size => 50, :d=>404 ), 'icon-user-unknown'] %>
17 17
18 <%= link_to( 18 <%= link_to(
19 image_tag(url_image, :onerror=>'gravatarCommentFailback(this)', 19 image_tag(url_image, :onerror=>'gravatarCommentFailback(this)',
20 - 'data-gravatar'=>str_gravatar_url_for(comment.email, :size=>50)) + 20 + 'data-gravatar'=>gravatar_profile_image_url(comment.email, :size=>50)) +
21 content_tag('span', comment.author_name, :class => 'comment-info') + 21 content_tag('span', comment.author_name, :class => 'comment-info') +
22 content_tag('span', comment.message, 22 content_tag('span', comment.message,
23 :class => 'comment-user-status ' + status_class), 23 :class => 'comment-user-status ' + status_class),
app/views/content_viewer/_article_toolbar.html.erb
@@ -52,6 +52,9 @@ @@ -52,6 +52,9 @@
52 52
53 </div> 53 </div>
54 <div id="article-header"> 54 <div id="article-header">
  55 + <% if @page.blog? and !@page.image.nil? %>
  56 + <div class="blog-cover"><%= image_tag(@page.image.public_filename())%></div>
  57 + <% end %>
55 <%= link_to(image_tag('icons-mime/rss-feed.png'), @page.feed.url, :class => 'blog-feed-link') if @page.has_posts? && @page.feed %> 58 <%= link_to(image_tag('icons-mime/rss-feed.png'), @page.feed.url, :class => 'blog-feed-link') if @page.has_posts? && @page.feed %>
56 <%= article_title(@page, :no_link => true) %> 59 <%= article_title(@page, :no_link => true) %>
57 <%= article_translations(@page) %> 60 <%= article_translations(@page) %>
app/views/content_viewer/_enterprise_homepage.html.erb
1 <%= display_profile_info enterprise_homepage.profile %> 1 <%= display_profile_info enterprise_homepage.profile %>
2 <div><%= enterprise_homepage.body %></div> 2 <div><%= enterprise_homepage.body %></div>
3 -<%= render :file => 'catalog/index' unless enterprise_homepage.profile.environment.enabled?('disable_products_for_enterprises') %> 3 +<%= render :file => 'catalog/index' if enterprise_homepage.profile.environment.enabled?('products_for_enterprises') %>
app/views/content_viewer/view_page.html.erb
@@ -14,6 +14,12 @@ @@ -14,6 +14,12 @@
14 window.NO_COMMENT_YET = "<%= _('No comments yet') %>"; 14 window.NO_COMMENT_YET = "<%= _('No comments yet') %>";
15 </script> 15 </script>
16 16
  17 +<% if @page.parent && !@page.parent.path.blank? %>
  18 +<div id="article-parent">
  19 + <%= button(:back, _('Go back to %s') % @page.parent.short_title, @page.parent.url) %>
  20 +</div>
  21 +<% end %>
  22 +
17 <div id="article-toolbar"></div> 23 <div id="article-toolbar"></div>
18 24
19 <script type="text/javascript"> 25 <script type="text/javascript">
@@ -43,11 +49,6 @@ @@ -43,11 +49,6 @@
43 </div> 49 </div>
44 <% end %> 50 <% end %>
45 51
46 -<% if @page.parent && !@page.parent.path.blank? %>  
47 -<div id="article-parent">  
48 - <%= button(:back, _('Go back to %s') % @page.parent.short_title, @page.parent.url) %>  
49 -</div>  
50 -<% end %>  
51 52
52 <%= render :partial => 'shared/disabled_enterprise' %> 53 <%= render :partial => 'shared/disabled_enterprise' %>
53 54
app/views/enterprise_registration/basic_information.html.erb
@@ -34,7 +34,7 @@ @@ -34,7 +34,7 @@
34 <% end %> 34 <% end %>
35 <% end %> 35 <% end %>
36 36
37 - <%= template_options(Enterprise, 'create_enterprise')%> 37 + <%= template_options(:enterprises, 'create_enterprise')%>
38 38
39 <% button_bar do %> 39 <% button_bar do %>
40 <%= submit_button('next', _('Next'), :cancel => {:profile => current_user.person.identifier, :action=>"enterprises", :controller=>"profile"}) %> 40 <%= submit_button('next', _('Next'), :cancel => {:profile => current_user.person.identifier, :action=>"enterprises", :controller=>"profile"}) %>
app/views/events/_agenda.html.erb
@@ -3,22 +3,14 @@ @@ -3,22 +3,14 @@
3 <table class='noborder current-month'> 3 <table class='noborder current-month'>
4 <caption> 4 <caption>
5 <h2><%= show_month(params[:year], params[:month]) %></h2> 5 <h2><%= show_month(params[:year], params[:month]) %></h2>
6 - <%= link_to_previous_month(params[:year], params[:month], '&laquo; %s' % _('previous')) %>  
7 - <%= link_to_next_month(params[:year], params[:month], '%s &raquo;' % _('next')) %> 6 + <%= link_to_previous_month(params[:year], params[:month], show_month(params[:year], params[:month], :previous => true, :only_month => true)) %>
  7 + <%= link_to_next_month(params[:year], params[:month], show_month(params[:year], params[:month], :next => true, :only_month => true)) %>
8 </caption> 8 </caption>
9 <%= render :partial => 'events/month', :locals => {:calendar => @calendar, :abbreviated => true} %> 9 <%= render :partial => 'events/month', :locals => {:calendar => @calendar, :abbreviated => true} %>
10 </table> 10 </table>
11 - <table class='noborder previous-month'>  
12 - <caption><h3><%= link_to_previous_month(params[:year], params[:month], show_month(params[:year], params[:month], :previous => true)) %></h3></caption>  
13 - <%= render :partial => 'events/month', :locals => {:calendar => @previous_calendar, :abbreviated => true} %>  
14 - </table>  
15 - <table class='noborder next-month'>  
16 - <caption><h3><%= link_to_next_month(params[:year], params[:month], show_month(params[:year], params[:month], :next => true)) %></h3></caption>  
17 - <%= render :partial => 'events/month', :locals => {:calendar => @next_calendar, :abbreviated => true} %>  
18 - </table>  
19 <br clear='both'/> 11 <br clear='both'/>
20 </div> 12 </div>
21 <div id='events-of-the-day'> 13 <div id='events-of-the-day'>
22 - <%= render :partial => 'events/events_by_day' %> 14 + <%= render :partial => 'events/events' %>
23 </div> 15 </div>
24 </div> 16 </div>
app/views/events/_events.rhtml 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +<%= list_events(@date, @events) %>
0 \ No newline at end of file 2 \ No newline at end of file
app/views/events/_events_by_day.html.erb
@@ -1 +0,0 @@ @@ -1 +0,0 @@
1 -<%= list_events(@selected_day, @events_of_the_day) %>  
app/views/file_presenter/_generic.html.erb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +<span class="download-link">
  2 + <span>Download</span>
  3 + <strong><%= link_to generic.filename, generic.public_filename %></strong>
  4 +</span>
  5 +
  6 +<div class="uploaded-file-description <%= 'empty' if generic.abstract.blank? %>">
  7 + <%= generic.abstract %>
  8 +</div>
  9 +
app/views/file_presenter/_image.html.erb 0 → 100644
@@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
  1 +<% if image.gallery? && options[:gallery_view] %>
  2 +<%
  3 + images = image.parent.images
  4 + current_index = images.index(image.encapsulated_file)
  5 + total_of_images = images.count
  6 + link_to_previous = if current_index >= 1
  7 + link_to(_('&laquo; Previous'), images[current_index - 1].view_url, :class => 'previous')
  8 + else
  9 + content_tag('span', _('&laquo; Previous'), :class => 'previous')
  10 + end
  11 +
  12 + link_to_next = if current_index < total_of_images - 1
  13 + link_to(_('Next &raquo;'), images[current_index + 1].view_url, :class => 'next')
  14 + else
  15 + content_tag('span', _('Next &raquo;'), :class => 'next')
  16 + end
  17 +%>
  18 +
  19 +<div class="gallery-navigation">
  20 + <%= link_to_previous %>
  21 + <span class="total-of-images">
  22 + <%= _('image %d of %d') % [current_index + 1, total_of_images] %>
  23 + </span>
  24 + <%= link_to_next %>
  25 +</div>
  26 +
  27 +<% end %>
  28 +
  29 +<%# image_tag(article.public_filename(:display), :class => article.css_class_name, :style => 'max-width: 100%') %>
  30 +
  31 +<img src="<%=image.public_filename(:display)%>" class="<%=image.css_class_name%>">
  32 +
  33 +<div class="uploaded-file-description <%= 'empty' if image.abstract.blank? %>">
  34 + <%= image.abstract %>
  35 +</div>
  36 +
app/views/manage_products/_display_price_details.html.erb
@@ -10,7 +10,7 @@ @@ -10,7 +10,7 @@
10 </li> 10 </li>
11 <% @product.price_details.each do |price_detail| %> 11 <% @product.price_details.each do |price_detail| %>
12 <li> 12 <li>
13 - <div class='price-detail-name'><%= "%s:" % price_detail.production_cost.name %></div> 13 + <div class='price-detail-name'><%= "%s:" % price_detail.name %></div>
14 <div class='price-detail-price'><%= float_to_currency(price_detail.price) %></div> 14 <div class='price-detail-price'><%= float_to_currency(price_detail.price) %></div>
15 </li> 15 </li>
16 <% end %> 16 <% end %>
app/views/manage_products/_edit_price_details.html.erb
1 <% price_details.each do |price_detail| %> 1 <% price_details.each do |price_detail| %>
2 <tr id='<%= "price-detail-#{price_detail.id}" %>'> 2 <tr id='<%= "price-detail-#{price_detail.id}" %>'>
3 <td><%= select_production_cost(@product, price_detail.production_cost_id) %></td> 3 <td><%= select_production_cost(@product, price_detail.production_cost_id) %></td>
4 - <td><%= labelled_form_field(environment.currency_unit, text_field_tag('price_details[][price]', price_detail.formatted_value(:price), :class => 'numbers-only price-details-price')) %></td> 4 + <td><%= labelled_form_field(environment.currency_unit, text_field_tag('price_details[][price]', price_detail.formatted_value(:price), :class => 'numbers-only price-details-price', :size => 6)) %></td>
5 <td> 5 <td>
6 <%= link_to_remote(_('Remove'), 6 <%= link_to_remote(_('Remove'),
7 :update => "price-detail-#{price_detail.id}", 7 :update => "price-detail-#{price_detail.id}",
app/views/manage_products/_manage_product_details.html.erb
@@ -34,7 +34,7 @@ @@ -34,7 +34,7 @@
34 <table id='new-cost-fields'> 34 <table id='new-cost-fields'>
35 <tr> 35 <tr>
36 <td><%= select_production_cost(@product) %></td> 36 <td><%= select_production_cost(@product) %></td>
37 - <td><%= labelled_form_field(environment.currency_unit, text_field_tag('price_details[][price]', nil, :class => 'numbers-only price-details-price')) %></td> 37 + <td><%= labelled_form_field(environment.currency_unit, text_field_tag('price_details[][price]', nil, :class => 'numbers-only price-details-price', :size => 6)) %></td>
38 <td><%= link_to(_('Cancel'), '#', {:class => 'cancel-new-cost'}) %></td> 38 <td><%= link_to(_('Cancel'), '#', {:class => 'cancel-new-cost'}) %></td>
39 </tr> 39 </tr>
40 </table> 40 </table>
app/views/maps/edit_location.html.erb
@@ -29,5 +29,5 @@ @@ -29,5 +29,5 @@
29 29
30 <% end %> 30 <% end %>
31 31
32 -<%= content_tag('script', '', :src => "http://maps.googleapis.com/maps/api/js?sensor=false", :type => 'text/javascript') %> 32 +<%= content_tag('script', '', :src => "https://maps.googleapis.com/maps/api/js?sensor=false", :type => 'text/javascript') %>
33 <%= content_tag('script', '', :src => url_for(:controller => :maps, :action => :google_map), :type => 'text/javascript') %> 33 <%= content_tag('script', '', :src => url_for(:controller => :maps, :action => :google_map), :type => 'text/javascript') %>
app/views/memberships/index.html.erb
@@ -8,6 +8,19 @@ @@ -8,6 +8,19 @@
8 <%= button :back, _('Go back'), :controller => 'profile_editor' %> 8 <%= button :back, _('Go back'), :controller => 'profile_editor' %>
9 <% end %> 9 <% end %>
10 10
11 -<%= render :partial => 'shared/list_groups', :locals => {:groups => @memberships} %> 11 +<% type_collection = [[nil, _('All')]] %>
  12 +<% type_collection += @roles.sort_by {|role| role.id}.map{|r| ["#{r.id}", r.name]} %>
  13 +
  14 +<p>
  15 + <%= labelled_select(_('Filter')+': ', :filter_type, :first, :last, @filter, type_collection, :onchange => 'document.location.href = "?filter_type="+this.value')%>
  16 +</p>
  17 +
  18 +<% if @memberships.empty? %>
  19 + <p>
  20 + <em><%= _('No groups to list') %></em>
  21 + </p>
  22 +<% else %>
  23 + <%= render :partial => 'shared/list_groups', :locals => {:groups => @memberships} %>
  24 +<% end %>
12 25
13 </div> 26 </div>
app/views/memberships/new_community.html.erb
@@ -44,11 +44,13 @@ @@ -44,11 +44,13 @@
44 </div> 44 </div>
45 </div> 45 </div>
46 46
47 - <%= template_options(Community, 'community')%> 47 + <%= template_options(:communities, 'community')%>
  48 +
  49 + <%= hidden_field_tag('back_to', @back_to) %>
48 50
49 <% button_bar do %> 51 <% button_bar do %>
50 <%= submit_button(:save, _('Create')) %> 52 <%= submit_button(:save, _('Create')) %>
51 - <%= button(:cancel, _('Cancel'), :action => 'index') %> 53 + <%= button(:cancel, _('Cancel'), @back_to ) %>
52 <% end %> 54 <% end %>
53 55
54 <% end %> 56 <% end %>