Commit e755c5668041d08027a61070fe94e5d9d0d154bc

Authored by Josef Spillner
2 parents 9a9bb082 86514f9d

Merge branch 'master' into feature_cyrillic

Showing 828 changed files with 79866 additions and 47407 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 828 files displayed.

AUTHORS
... ... @@ -6,25 +6,42 @@ noosfero, that's not a problem).
6 6 Developers
7 7 ==========
8 8  
  9 +Antonio Terceiro + Carlos Morais <terceiro@colivre.coop.br>
  10 +Antonio Terceiro + Paulo Meirelles <terceiro@colivre.coop.br>
9 11 Antonio Terceiro <terceiro@colivre.coop.br>
10 12 Aurelio A. Heckert <aurelio@colivre.coop.br>
11 13 Braulio Bhavamitra <brauliobo@gmail.com>
12 14 Bráulio Bhavamitra <brauliobo@gmail.com>
13 15 Caio SBA <caio@colivre.coop.br>
  16 +Carlos Morais <carlos88morais@gmail.com>
  17 +Carlos Morais + Diego Araújo <diegoamc90@gmail.com>
  18 +Carlos Morais + Paulo Meirelles <carlos88morais@gmail.com>
14 19 Daniela Soares Feitosa <danielafeitosa@colivre.coop.br>
15 20 Daniel Cunha <daniel@colivre.coop.br>
  21 +Diego Araújo <diegoamc90@gmail.com>
  22 +Diego Araújo + João M. M. da Silva <diegoamc90@gmail.com>
16 23 Fernanda Lopes <nanda.listas+psl@gmail.com>
17 24 Grazieno Pellegrino <grazieno@gmail.com>
18 25 Italo Valcy <italo@dcc.ufba.br>
  26 +João da Silva <jaodsilv@linux.ime.usp.br>
  27 +João M. M. da Silva + Carlos Morais <jaodsilv@linux.ime.usp.br>
  28 +João M. M. da Silva + Diego Araújo <diegoamc90@gmail.com>
  29 +João M. M. da Silva + Diego Araújo <jaodsilv@linux.ime.usp.br>
  30 +João M. M. da Silva + Paulo Meirelles <jaodsilv@linux.ime.usp.br>
19 31 Joenio Costa <joenio@colivre.coop.br>
20 32 Josef Spillner <josef.spillner@tu-dresden.de>
21 33 Keilla Menezes <keilla@colivre.coop.br>
  34 +Larissa Reis <larissa@colivre.coop.br>
  35 +Larissa Reis <reiss.larissa@gmail.com>
22 36 Leandro Nunes dos Santos <leandronunes@gmail.com>
23 37 LinguÁgil 2010 <linguagil.bahia@gmail.com>
24 38 Martín Olivera <molivera@solar.org.ar>
25 39 Moises Machado <moises@colivre.coop.br>
26 40 Nanda Lopes <nanda.listas+psl@gmail.com>
  41 +Paulo Meirelles + Carlos Morais <paulo@softwarelivre.org>
  42 +Paulo Meirelles <paulo@softwarelivre.org>
27 43 Rafael Gomes <rafaelgomes@techfree.com.br>
  44 +Rafael Martins <rmmartins@gmail.com>
28 45 Raphaël Rousseau <raph@r4f.org>
29 46 Raquel Lira <raquel.lira@gmail.com>
30 47 Rodrigo Souto <rodrigo@colivre.coop.br>
... ... @@ -41,3 +58,6 @@ Raphael Rousseau &lt;raph@r4f.org&gt;
41 58 Théo Bondolfi <move@cooperation.net>
42 59 Vicente Aguiar <vicenteaguiar@colivre.coop.br>
43 60  
  61 +Arts
  62 +===================================
  63 +Nara Oliveira <narananet@gmail.com>
... ...
Gemfile 0 → 100644
... ... @@ -0,0 +1,19 @@
  1 +source :rubygems
  2 +gem 'cucumber', '0.4.0'
  3 +gem 'webrat', '0.5.1'
  4 +gem 'rspec', '1.2.9'
  5 +gem 'rspec-rails', '1.2.9'
  6 +gem 'Selenium', '>= 1.1.14'
  7 +gem 'selenium-client', '>= 1.2.17'
  8 +gem 'database_cleaner'
  9 +gem 'exception_notification', '1.0.20090728'
  10 +gem 'system_timer'
  11 +
  12 +def program(name)
  13 + unless system("which #{name} > /dev/null")
  14 + puts "W: Program #{name} is needed, but was not found in your PATH"
  15 + end
  16 +end
  17 +
  18 +program 'java'
  19 +program 'firefox'
... ...
Gemfile.lock 0 → 100644
... ... @@ -0,0 +1,44 @@
  1 +GEM
  2 + remote: http://rubygems.org/
  3 + specs:
  4 + Selenium (1.1.14)
  5 + builder (3.0.0)
  6 + cucumber (0.4.0)
  7 + builder (>= 2.1.2)
  8 + diff-lcs (>= 1.1.2)
  9 + polyglot (>= 0.2.9)
  10 + term-ansicolor (>= 1.0.3)
  11 + treetop (>= 1.4.2)
  12 + database_cleaner (0.7.0)
  13 + diff-lcs (1.1.3)
  14 + exception_notification (1.0.20090728)
  15 + nokogiri (1.5.0)
  16 + polyglot (0.3.3)
  17 + rack (1.3.5)
  18 + rspec (1.2.9)
  19 + rspec-rails (1.2.9)
  20 + rack (>= 1.0.0)
  21 + rspec (>= 1.2.9)
  22 + selenium-client (1.2.18)
  23 + system_timer (1.2.4)
  24 + term-ansicolor (1.0.7)
  25 + treetop (1.4.10)
  26 + polyglot
  27 + polyglot (>= 0.3.1)
  28 + webrat (0.5.1)
  29 + nokogiri (>= 1.2.0)
  30 + rack (>= 1.0)
  31 +
  32 +PLATFORMS
  33 + ruby
  34 +
  35 +DEPENDENCIES
  36 + Selenium (>= 1.1.14)
  37 + cucumber (= 0.4.0)
  38 + database_cleaner
  39 + exception_notification (= 1.0.20090728)
  40 + rspec (= 1.2.9)
  41 + rspec-rails (= 1.2.9)
  42 + selenium-client (>= 1.2.17)
  43 + system_timer
  44 + webrat (= 0.5.1)
... ...
HACKING
... ... @@ -13,7 +13,7 @@ After installing the requirements listed in INSTALL, you need to install some
13 13 packages be able to run Noosfero tests. On Debian GNU/Linux and Debian-based
14 14 systems, you install them with the following command:
15 15  
16   - # apt-get install libtidy-ruby libhpricot-ruby libmocha-ruby imagemagick po4a xvfb
  16 + # apt-get install libtidy-ruby libhpricot-ruby libmocha-ruby imagemagick po4a xvfb libxml2-dev libxslt-dev
17 17  
18 18 On other systems, they may or may not be available through your regular package
19 19 management system. Below are the links to their homepages.
... ... @@ -24,6 +24,8 @@ management system. Below are the links to their homepages.
24 24 * Imagemagick: http://wwwimagemagick.org/
25 25 * po4a: http://po4a.alioth.debian.org/
26 26 * xvfb: http://packages.debian.org/lenny/xvfb
  27 +* Libxml2: http://xmlsoft.org/
  28 +* Libxslt: http://xmlsoft.org/xslt
27 29  
28 30 == Boostraping a development/test environment
29 31  
... ... @@ -46,6 +48,9 @@ commands and make sure you understand what you are doing):
46 48 rake makemo
47 49 # create some test data:
48 50 ./script/sample-data
  51 + # install latest requirements for running tests
  52 + RAILS_ENV=cucumber rake gems:install
  53 + RAILS_ENV=test rake gems:install
49 54 # run the automated test suite to make sure your environment is sane:
50 55 rake test
51 56  
... ...
HACKING.rails235 0 → 100644
... ... @@ -0,0 +1,14 @@
  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 ferret
  8 +gem install i18n
  9 +gem install will_paginate -v 2.3.12
  10 +gem install cucumber
  11 +
  12 +Creating initial environment:
  13 +
  14 +rake db:schema:load
... ...
INSTALL
... ... @@ -13,7 +13,7 @@ You need to install some packages Noosfero depends on. On Debian GNU/Linux or
13 13 Debian-based systems, all of these packages are available through the Debian
14 14 archive. You can install them with the following command:
15 15  
16   - # apt-get install ruby rake po4a libgettext-ruby-util libgettext-ruby-data libgettext-ruby1.8 libsqlite3-ruby rcov librmagick-ruby libredcloth-ruby libwill-paginate-ruby iso-codes libfeedparser-ruby libferret-ruby libdaemons-ruby mongrel mongrel-cluster tango-icon-theme libhpricot-ruby
  16 + # apt-get install ruby rake po4a libgettext-ruby-util libgettext-ruby-data libgettext-ruby1.8 libsqlite3-ruby rcov librmagick-ruby libredcloth-ruby libwill-paginate-ruby iso-codes libfeedparser-ruby libferret-ruby libdaemons-ruby thin tango-icon-theme libhpricot-ruby
17 17  
18 18 On other systems, they may or may not be available through your regular package
19 19 management system. Below are the links to their homepages.
... ... @@ -31,7 +31,7 @@ management system. Below are the links to their homepages.
31 31 * iso-codes: http://pkg-isocodes.alioth.debian.org/
32 32 * feedparser: http://packages.debian.org/sid/libfeedparser-ruby
33 33 * Daemons - http://daemons.rubyforge.org/
34   -* Mongrel: http://mongrel.rubyforge.org/
  34 +* Thin: http://code.macournoyer.com/thin/
35 35 * tango-icon-theme: http://tango.freedesktop.org/Tango_Icon_Library
36 36 * Hpricot: http://hpricot.com/
37 37  
... ... @@ -118,13 +118,13 @@ $ cd current
118 118 Copy config/ferret_server.yml.dist to config/ferret_server.yml. You will
119 119 probably not need to customize this configuration, but have a look at it.
120 120  
121   -Create the mongrel configuration file:
  121 +Create the thin configuration file:
122 122  
123   -$ mongrel_rails cluster::configure
  123 +$ thin -C config/thin.yml config
124 124  
125   -Edit config/mongrel_cluster.yml to suit your needs. Make sure your apache
126   -configuration matches the mongrel cluster configuration, specially in respect
127   -to the ports and numbers of mongrel instances.
  125 +Edit config/thin.yml to suit your needs. Make sure your apache
  126 +configuration matches the thin cluster configuration, specially in respect
  127 +to the ports and numbers of thin instances.
128 128  
129 129 Note: currently Noosfero only supports Rails 2.1.0, which is the version in
130 130 Debian Lenny. If you have a Rails version newer than that, Noosfero will
... ... @@ -237,6 +237,10 @@ Create the database structure:
237 237  
238 238 $ RAILS_ENV=production rake db:schema:load
239 239  
  240 +Compile the translations:
  241 +
  242 +$ RAILS_ENV=production rake noosfero:translations:compile
  243 +
240 244 Now we have to create some initial data. To create your default environment
241 245 (the first one), run the command below:
242 246  
... ... @@ -258,10 +262,6 @@ $ RAILS_ENV=production ./script/runner &quot;User.create(:login =&gt; &#39;adminuser&#39;, :emai
258 262 (replace "adminuser", "admin@example.com", "admin" with the login, email
259 263 and password of your environment admin)
260 264  
261   -Compile the translations:
262   -
263   -$ RAILS_ENV=production rake noosfero:translations:compile
264   -
265 265 To start the Noosfero application servers:
266 266  
267 267 $ ./script/production start
... ... @@ -316,7 +316,7 @@ In other systems the way by which you enable apache modules may be different.
316 316 Now with the Apache configuration. You can use the template below, replacing
317 317 /var/lib/noosfero/current with the directory in which your noosfero
318 318 installation is, your.domain.com with the domain name of your noosfero site.
319   -We are assuming that you are running two mongrel instances on ports 3000 and
  319 +We are assuming that you are running two thin instances on ports 3000 and
320 320 3001. If your setup is different you'll need to adjust <Proxy> section. If you
321 321 don't understand something in the configuration, please refer to the apache
322 322 documentation.
... ...
INSTALL.awstats 0 → 100644
... ... @@ -0,0 +1,78 @@
  1 += AWStats setup for Noosfero
  2 +
  3 +AWStats is a free powerful and featureful tool that generates advanced web,
  4 +streaming, ftp or mail server statistics, graphically.
  5 +
  6 +See http://awstats.sourceforge.net/
  7 +
  8 +This guide supposes that the Noosfero server is running GNU/Linux Debian Squeeze.
  9 +
  10 +1. Install AWStats
  11 +
  12 +# apt-get install awstats libgeo-ip-perl geoip-database
  13 +
  14 +2. Basic setup
  15 +
  16 +Create AWStats config file:
  17 +
  18 + * /etc/awstats/awstats.<domain>.conf
  19 +
  20 +Include "/etc/awstats/awstats.conf"
  21 +Include "/etc/noosfero/awstats-noosfero.conf"
  22 +SiteDomain="<domain>"
  23 +HostAliases="<domain-aliases>"
  24 +
  25 +<domain> should be the domain used in your Noosfero server (eg.:
  26 +softwarelivre.org) and the <domain-aliases> should be a list with all aliases
  27 +that you configured in apache (eg.: www.softwarelivre.org
  28 +www2.softwarelivre.org etc).
  29 +
  30 +This setup is considering that the Noosfero server is running varnish (see
  31 +INSTALL.varnish) and varnishncsa-vhost [1].
  32 +
  33 +[1] http://gitorious.org/varnisnncsa-vhost
  34 +
  35 +3. Running AWStats for the first time
  36 +
  37 +Run awstats by hand via command line:
  38 +
  39 +# /usr/lib/cgi-bin/awstats.pl -config=<domain>
  40 +
  41 +You should see something as below as output of this command:
  42 +
  43 +# /usr/lib/cgi-bin/awstats.pl -config=softwarelivre.org
  44 +Create/Update database for config "/etc/awstats/awstats.softwarelivre.org.conf" by AWStats version 6.7 (build 1.892)
  45 +From data in log file "/var/log/varnish/varnishncsa-vhost.log"...
  46 +Phase 1 : First bypass old records, searching new record...
  47 +Searching new records from beginning of log file...
  48 +Phase 2 : Now process new records (Flush history on disk after 20000 hosts)...
  49 +Jumped lines in file: 0
  50 +Parsed lines in file: 452
  51 + Found 0 dropped records,
  52 + Found 0 corrupted records,
  53 + Found 0 old records,
  54 + Found 452 new qualified records.
  55 +
  56 +4. Setup frontend
  57 +
  58 +You should create a new subdomain to have access to the AWStats, usually
  59 +something like tools.<domain> (eg.: tools.softwarelivre.org). Don't include
  60 +this subdomain in HostAliases in the AWStats neither in SiteAlias in the
  61 +Apache.
  62 +
  63 +# cp /usr/share/doc/awstats/examples/apache.conf /etc/apache2/conf.d/awstats.conf
  64 +# invoke-rc.d apache2 restart
  65 +
  66 +ps.: Don't forget to change the port /etc/apache/sites-enabled/000-default to
  67 +8080.
  68 +
  69 +Try: http://tools.<domain>/cgi-bin/awstats.pl?config=<domain>
  70 +(eg.: http://tools.softwarelivre.org/cgi-bin/awstats.pl?config=softwarelivre.org).
  71 +
  72 +5. Schedule AWStats in crontab
  73 +
  74 + * /etc/cron.d/awstats
  75 +
  76 +0,10,20,30,40,50 * * * * www-data [ -x /usr/lib/cgi-bin/awstats.pl -a -f /etc/awstats/awstats.<domain>.conf -a -r /var/log/apache/access.log ] && /usr/lib/cgi-bin/awstats.pl -config=<domain> -update >/dev/null
  77 +
  78 +Done, check the AWStats frontend after one or two days to see if everything is working properly.
... ...
app/controllers/admin/role_controller.rb
... ... @@ -5,6 +5,20 @@ class RoleController &lt; AdminController
5 5 @roles = environment.roles.find(:all)
6 6 end
7 7  
  8 + def new
  9 + @role = Role.new
  10 + end
  11 +
  12 + def create
  13 + @role = Role.new :name => params[:role][:name], :permissions => params[:role][:permissions], :environment => environment
  14 + if @role.save
  15 + redirect_to :action => 'show', :id => @role
  16 + else
  17 + session[:notice] = _('Failed to create role')
  18 + render :action => 'new'
  19 + end
  20 + end
  21 +
8 22 def show
9 23 @role = environment.roles.find(params[:id])
10 24 end
... ...
app/controllers/admin/users_controller.rb
... ... @@ -3,10 +3,10 @@ class UsersController &lt; AdminController
3 3 protect 'manage_environment_users', :environment
4 4  
5 5 def index
6   - @users = environment.users
7 6 respond_to do |format|
8 7 format.html
9 8 format.xml do
  9 + @users = User.find(:all, :conditions => {:environment_id => environment.id}, :include => [:person])
10 10 render :xml => @users.to_xml(
11 11 :skip_types => true,
12 12 :only => %w[email login created_at updated_at],
... ... @@ -14,6 +14,7 @@ class UsersController &lt; AdminController
14 14 )
15 15 end
16 16 format.csv do
  17 + @users = User.find(:all, :conditions => {:environment_id => environment.id}, :include => [:person])
17 18 render :template => "users/index_csv.rhtml", :content_type => 'text/csv', :layout => false
18 19 end
19 20 end
... ...
app/controllers/admin_controller.rb
1 1 class AdminController < ApplicationController
2   - require_ssl
3 2 before_filter :login_required
4 3 end
... ...
app/controllers/application.rb
1   -# his is the application's main controller. Features defined here are
2   -# available in all controllers.
3   -class ApplicationController < ActionController::Base
4   -
5   - before_filter :change_pg_schema
6   -
7   - include ApplicationHelper
8   - layout :get_layout
9   - def get_layout
10   - theme_option(:layout) || 'application'
11   - end
12   -
13   - filter_parameter_logging :password
14   -
15   - def log_processing
16   - super
17   - return unless ENV['RAILS_ENV'] == 'production'
18   - if logger && logger.info?
19   - logger.info(" HTTP Referer: #{request.referer}")
20   - logger.info(" User Agent: #{request.user_agent}")
21   - logger.info(" Accept-Language: #{request.headers['HTTP_ACCEPT_LANGUAGE']}")
22   - end
23   - end
24   -
25   - helper :document
26   - helper :language
27   -
28   - def self.no_design_blocks
29   - @no_design_blocks = true
30   - end
31   - def self.uses_design_blocks?
32   - !@no_design_blocks
33   - end
34   - def uses_design_blocks?
35   - !@no_design_blocks && self.class.uses_design_blocks?
36   - end
37   -
38   - # Be sure to include AuthenticationSystem in Application Controller instead
39   - include AuthenticatedSystem
40   - include PermissionCheck
41   -
42   - def self.require_ssl(*options)
43   - before_filter :check_ssl, *options
44   - end
45   - def check_ssl
46   - return true if (request.ssl? || ENV['RAILS_ENV'] == 'development')
47   - redirect_to_ssl
48   - end
49   - def redirect_to_ssl
50   - if environment.enable_ssl
51   - redirect_to(params.merge(:protocol => 'https://', :host => ssl_hostname))
52   - true
53   - else
54   - false
55   - end
56   - end
57   -
58   - def self.refuse_ssl(*options)
59   - before_filter :avoid_ssl, *options
60   - end
61   - def avoid_ssl
62   - if (!request.ssl? || ENV['RAILS_ENV'] == 'development')
63   - true
64   - else
65   - redirect_to(params.merge(:protocol => 'http://'))
66   - false
67   - end
68   - end
69   -
70   - before_filter :set_locale
71   - def set_locale
72   - FastGettext.available_locales = Noosfero.available_locales
73   - FastGettext.default_locale = Noosfero.default_locale
74   - FastGettext.set_locale(params[:lang] || session[:lang] || Noosfero.default_locale || request.env['HTTP_ACCEPT_LANGUAGE'] || 'en')
75   - if params[:lang]
76   - session[:lang] = params[:lang]
77   - end
78   - end
79   -
80   - include NeedsProfile
81   -
82   - before_filter :detect_stuff_by_domain
83   - before_filter :init_noosfero_plugins
84   - attr_reader :environment
85   -
86   - before_filter :load_terminology
87   -
88   - # declares that the given <tt>actions</tt> cannot be accessed by other HTTP
89   - # method besides POST.
90   - def self.post_only(actions, redirect = { :action => 'index'})
91   - verify :method => :post, :only => actions, :redirect_to => redirect
92   - end
93   -
94   - helper_method :current_person, :current_person
95   -
96   - def change_pg_schema
97   - if Noosfero::MultiTenancy.on? and ActiveRecord::Base.postgresql?
98   - Noosfero::MultiTenancy.db_by_host = request.host
99   - end
100   - end
101   -
102   - protected
103   -
104   - def boxes_editor?
105   - false
106   - end
107   -
108   - def content_editor?
109   - false
110   - end
111   -
112   - def user
113   - current_user.person if logged_in?
114   - end
115   -
116   - alias :current_person :user
117   -
118   - # TODO: move this logic somewhere else (Domain class?)
119   - def detect_stuff_by_domain
120   - @domain = Domain.find_by_name(request.host)
121   - if @domain.nil?
122   - @environment = Environment.default
123   - else
124   - @environment = @domain.environment
125   - @profile = @domain.profile
126   - end
127   - end
128   -
129   - def init_noosfero_plugins
130   - @plugins = Noosfero::Plugin::Manager.new(self)
131   - @plugins.enabled_plugins.map(&:class).each do |plugin|
132   - prepend_view_path(plugin.view_path)
133   - end
134   - init_noosfero_plugins_controller_filters
135   - end
136   -
137   - # This is a generic method that initialize any possible filter defined by a
138   - # plugin to the current controller being initialized.
139   - def init_noosfero_plugins_controller_filters
140   - @plugins.enabled_plugins.each do |plugin|
141   - plugin.send(self.class.name.underscore + '_filters').each do |plugin_filter|
142   - self.class.send(plugin_filter[:type], plugin.class.name.underscore + '_' + plugin_filter[:method_name], (plugin_filter[:options] || {}))
143   - self.class.send(:define_method, plugin.class.name.underscore + '_' + plugin_filter[:method_name], plugin_filter[:block])
144   - end
145   - end
146   - end
147   -
148   - def load_terminology
149   - # cache terminology for performance
150   - @@terminology_cache ||= {}
151   - @@terminology_cache[environment.id] ||= environment.terminology
152   - Noosfero.terminology = @@terminology_cache[environment.id]
153   - end
154   -
155   - def render_not_found(path = nil)
156   - @no_design_blocks = true
157   - @path ||= request.path
158   - render :template => 'shared/not_found.rhtml', :status => 404, :layout => get_layout
159   - end
160   - alias :render_404 :render_not_found
161   -
162   - def render_access_denied(message = nil, title = nil)
163   - @no_design_blocks = true
164   - @message = message
165   - @title = title
166   - render :template => 'shared/access_denied.rhtml', :status => 403
167   - end
168   -
169   - def load_category
170   - unless params[:category_path].blank?
171   - path = params[:category_path].join('/')
172   - @category = environment.categories.find_by_path(path)
173   - if @category.nil?
174   - render_not_found(path)
175   - end
176   - end
177   - end
178   -
179   -end
  1 +require 'application_controller'
... ...
app/controllers/application_controller.rb 0 → 100644
... ... @@ -0,0 +1,155 @@
  1 +class ApplicationController < ActionController::Base
  2 +
  3 + before_filter :change_pg_schema
  4 +
  5 + include ApplicationHelper
  6 + layout :get_layout
  7 + def get_layout
  8 + prepend_view_path('public/' + theme_path)
  9 + theme_option(:layout) || 'application'
  10 + end
  11 +
  12 + filter_parameter_logging :password
  13 +
  14 + def log_processing
  15 + super
  16 + return unless ENV['RAILS_ENV'] == 'production'
  17 + if logger && logger.info?
  18 + logger.info(" HTTP Referer: #{request.referer}")
  19 + logger.info(" User Agent: #{request.user_agent}")
  20 + logger.info(" Accept-Language: #{request.headers['HTTP_ACCEPT_LANGUAGE']}")
  21 + end
  22 + end
  23 +
  24 + helper :document
  25 + helper :language
  26 +
  27 + def self.no_design_blocks
  28 + @no_design_blocks = true
  29 + end
  30 + def self.uses_design_blocks?
  31 + !@no_design_blocks
  32 + end
  33 + def uses_design_blocks?
  34 + !@no_design_blocks && self.class.uses_design_blocks?
  35 + end
  36 +
  37 + # Be sure to include AuthenticationSystem in Application Controller instead
  38 + include AuthenticatedSystem
  39 + include PermissionCheck
  40 +
  41 + before_filter :set_locale
  42 + def set_locale
  43 + FastGettext.available_locales = Noosfero.available_locales
  44 + FastGettext.default_locale = Noosfero.default_locale
  45 + I18n.locale = FastGettext.locale = (params[:lang] || session[:lang] || Noosfero.default_locale || request.env['HTTP_ACCEPT_LANGUAGE'] || 'en')
  46 + if params[:lang]
  47 + session[:lang] = params[:lang]
  48 + end
  49 + end
  50 +
  51 + include NeedsProfile
  52 +
  53 + before_filter :detect_stuff_by_domain
  54 + before_filter :init_noosfero_plugins
  55 + attr_reader :environment
  56 +
  57 + before_filter :load_terminology
  58 +
  59 + # declares that the given <tt>actions</tt> cannot be accessed by other HTTP
  60 + # method besides POST.
  61 + def self.post_only(actions, redirect = { :action => 'index'})
  62 + verify :method => :post, :only => actions, :redirect_to => redirect
  63 + end
  64 +
  65 + helper_method :current_person, :current_person
  66 +
  67 + protected
  68 +
  69 + def change_pg_schema
  70 + if Noosfero::MultiTenancy.on? and ActiveRecord::Base.postgresql?
  71 + Noosfero::MultiTenancy.db_by_host = request.host
  72 + end
  73 + end
  74 +
  75 + def boxes_editor?
  76 + false
  77 + end
  78 +
  79 + def content_editor?
  80 + false
  81 + end
  82 +
  83 +
  84 + def user
  85 + current_user.person if logged_in?
  86 + end
  87 +
  88 + alias :current_person :user
  89 +
  90 + # TODO: move this logic somewhere else (Domain class?)
  91 + def detect_stuff_by_domain
  92 + @domain = Domain.find_by_name(request.host)
  93 + if @domain.nil?
  94 + @environment = Environment.default
  95 + if @environment.nil? && Rails.env.development?
  96 + # This should only happen in development ...
  97 + @environment = Environment.create!(:name => "Noosfero", :is_default => true)
  98 + end
  99 + else
  100 + @environment = @domain.environment
  101 + @profile = @domain.profile
  102 + end
  103 + end
  104 +
  105 + def init_noosfero_plugins
  106 + @plugins = Noosfero::Plugin::Manager.new(self)
  107 + @plugins.each do |plugin|
  108 + prepend_view_path(plugin.class.view_path)
  109 + end
  110 + init_noosfero_plugins_controller_filters
  111 + end
  112 +
  113 + # This is a generic method that initialize any possible filter defined by a
  114 + # plugin to the current controller being initialized.
  115 + def init_noosfero_plugins_controller_filters
  116 + @plugins.each do |plugin|
  117 + plugin.send(self.class.name.underscore + '_filters').each do |plugin_filter|
  118 + self.class.send(plugin_filter[:type], plugin.class.name.underscore + '_' + plugin_filter[:method_name], (plugin_filter[:options] || {}))
  119 + self.class.send(:define_method, plugin.class.name.underscore + '_' + plugin_filter[:method_name], plugin_filter[:block])
  120 + end
  121 + end
  122 + end
  123 +
  124 + def load_terminology
  125 + # cache terminology for performance
  126 + @@terminology_cache ||= {}
  127 + @@terminology_cache[environment.id] ||= environment.terminology
  128 + Noosfero.terminology = @@terminology_cache[environment.id]
  129 + end
  130 +
  131 + def render_not_found(path = nil)
  132 + @no_design_blocks = true
  133 + @path ||= request.path
  134 + render :template => 'shared/not_found.rhtml', :status => 404, :layout => get_layout
  135 + end
  136 + alias :render_404 :render_not_found
  137 +
  138 + def render_access_denied(message = nil, title = nil)
  139 + @no_design_blocks = true
  140 + @message = message
  141 + @title = title
  142 + render :template => 'shared/access_denied.rhtml', :status => 403
  143 + end
  144 +
  145 + def load_category
  146 + unless params[:category_path].blank?
  147 + path = params[:category_path].join('/')
  148 + @category = environment.categories.find_by_path(path)
  149 + if @category.nil?
  150 + render_not_found(path)
  151 + end
  152 + end
  153 + end
  154 +
  155 +end
... ...
app/controllers/box_organizer_controller.rb
... ... @@ -82,7 +82,6 @@ class BoxOrganizerController &lt; ApplicationController
82 82 def save
83 83 @block = boxes_holder.blocks.find(params[:id])
84 84 @block.update_attributes(params[:block])
85   - expire_timeout_fragment(@block.cache_key)
86 85 redirect_to :action => 'index'
87 86 end
88 87  
... ... @@ -93,7 +92,6 @@ class BoxOrganizerController &lt; ApplicationController
93 92 def remove
94 93 @block = Block.find(params[:id])
95 94 if @block.destroy
96   - expire_timeout_fragment(@block.cache_key)
97 95 redirect_to :action => 'index'
98 96 else
99 97 session[:notice] = _('Failed to remove block')
... ...
app/controllers/my_profile/cms_controller.rb
... ... @@ -23,15 +23,6 @@ class CmsController &lt; MyProfileController
23 23 profile.articles.find(c.params[:id]).allow_post_content?(user)
24 24 end
25 25  
26   - alias :check_ssl_orig :check_ssl
27   - # Redefines the SSL checking to avoid requiring SSL when creating the "New
28   - # publication" button on article's public view.
29   - def check_ssl
30   - if ((params[:action] == 'new') && (!request.xhr?)) || (params[:action] != 'new')
31   - check_ssl_orig
32   - end
33   - end
34   -
35 26 def boxes_holder
36 27 profile
37 28 end
... ... @@ -59,7 +50,7 @@ class CmsController &lt; MyProfileController
59 50 end
60 51  
61 52 def special_article_types
62   - [Folder, Blog, UploadedFile, Forum, Gallery, RssFeed]
  53 + [Folder, Blog, UploadedFile, Forum, Gallery, RssFeed] + @plugins.dispatch(:content_types)
63 54 end
64 55  
65 56 def view
... ... @@ -206,6 +197,7 @@ class CmsController &lt; MyProfileController
206 197 @article = profile.articles.find(params[:id])
207 198 if request.post?
208 199 @article.destroy
  200 + session[:notice] = _("\"#{@article.name}\" was removed.")
209 201 redirect_to :action => (@article.parent ? 'view' : 'index'), :id => @article.parent
210 202 end
211 203 end
... ... @@ -319,10 +311,6 @@ class CmsController &lt; MyProfileController
319 311 end
320 312 end
321 313  
322   - def maybe_ssl(url)
323   - [url, url.sub('https:', 'http:')]
324   - end
325   -
326 314 def valid_article_type?(type)
327 315 (available_article_types + special_article_types).map {|item| item.name}.include?(type)
328 316 end
... ... @@ -365,7 +353,7 @@ class CmsController &lt; MyProfileController
365 353 }
366 354 end.to_json
367 355 end
368   -
  356 +
369 357 def content_editor?
370 358 true
371 359 end
... ...
app/controllers/my_profile/manage_products_controller.rb
... ... @@ -111,6 +111,36 @@ class ManageProductsController &lt; ApplicationController
111 111 end
112 112 end
113 113  
  114 + def manage_product_details
  115 + @product = @profile.products.find(params[:id])
  116 + if request.post?
  117 + @product.update_price_details(params[:price_details]) if params[:price_details]
  118 + render :partial => 'display_price_details'
  119 + else
  120 + render :partial => 'manage_product_details'
  121 + end
  122 + end
  123 +
  124 + def remove_price_detail
  125 + @product = @profile.products.find(params[:product])
  126 + @price_detail = @product.price_details.find(params[:id])
  127 + @product = @price_detail.product
  128 + if request.post?
  129 + @price_detail.destroy
  130 + render :nothing => true
  131 + end
  132 + end
  133 +
  134 + def display_price_composition_bar
  135 + @product = @profile.products.find(params[:id])
  136 + render :partial => 'price_composition_bar'
  137 + end
  138 +
  139 + def display_inputs_cost
  140 + @product = @profile.products.find(params[:id])
  141 + render :inline => "<%= float_to_currency(@product.inputs_cost) %>"
  142 + end
  143 +
114 144 def destroy
115 145 @product = @profile.products.find(params[:id])
116 146 if @product.destroy
... ... @@ -167,4 +197,18 @@ class ManageProductsController &lt; ApplicationController
167 197 end
168 198 end
169 199  
  200 + def create_production_cost
  201 + cost = @profile.production_costs.create(:name => params[:id])
  202 + if cost.valid?
  203 + cost.save
  204 + render :text => {:name => cost.name,
  205 + :id => cost.id,
  206 + :ok => true
  207 + }.to_json
  208 + else
  209 + render :text => {:ok => false,
  210 + :error_msg => _(cost.errors['name']) % {:fn => _('Name')}
  211 + }.to_json
  212 + end
  213 + end
170 214 end
... ...
app/controllers/my_profile/tasks_controller.rb
... ... @@ -33,12 +33,14 @@ class TasksController &lt; MyProfileController
33 33 end
34 34 end
35 35  
  36 + url = { :action => 'index' }
36 37 if failed.blank?
37 38 session[:notice] = _("All decisions were applied successfully.")
38 39 else
39 40 session[:notice] = _("Some decisions couldn't be applied.")
  41 + url[:failed] = failed
40 42 end
41   - redirect_to params.merge!(:action => 'index', :failed => failed)
  43 + redirect_to url
42 44 end
43 45  
44 46 def new
... ...
app/controllers/my_profile_controller.rb
... ... @@ -2,7 +2,6 @@ class MyProfileController &lt; ApplicationController
2 2  
3 3 needs_profile
4 4  
5   - require_ssl
6 5  
7 6 before_filter :login_required
8 7  
... ...
app/controllers/public/account_controller.rb
... ... @@ -2,8 +2,6 @@ class AccountController &lt; ApplicationController
2 2  
3 3 no_design_blocks
4 4  
5   - require_ssl :except => [ :login_popup, :logout_popup, :profile_details ]
6   -
7 5 before_filter :login_required, :only => [:activation_question, :accept_terms, :activate_enterprise]
8 6 before_filter :redirect_if_logged_in, :only => [:login, :signup]
9 7  
... ... @@ -60,6 +58,10 @@ class AccountController &lt; ApplicationController
60 58 def signup
61 59 @invitation_code = params[:invitation_code]
62 60 begin
  61 + if params[:user]
  62 + params[:user].delete(:password_confirmation_clear)
  63 + params[:user].delete(:password_clear)
  64 + end
63 65 @user = User.new(params[:user])
64 66 @user.terms_of_use = environment.terms_of_use
65 67 @user.environment = environment
... ... @@ -91,7 +93,6 @@ class AccountController &lt; ApplicationController
91 93 if logged_in?
92 94 self.current_user.forget_me
93 95 end
94   - cookies.delete :auth_token
95 96 reset_session
96 97 session[:notice] = _("You have been logged out.")
97 98 redirect_to :controller => 'home', :action => 'index'
... ... @@ -209,16 +210,26 @@ class AccountController &lt; ApplicationController
209 210 @identifier = params[:identifier]
210 211 valid = Person.is_available?(@identifier, environment)
211 212 if valid
212   - @status = _('Available!')
  213 + @status = _('This login name is available')
213 214 @status_class = 'available'
214 215 else
215   - @status = _('Unavailable!')
  216 + @status = _('This login name is unavailable')
216 217 @status_class = 'unavailable'
217 218 end
218   - @url = environment.top_url + '/' + @identifier
219 219 render :partial => 'identifier_status'
220 220 end
221 221  
  222 + def check_email
  223 + if User.find_by_email_and_environment_id(params[:address], environment.id).nil?
  224 + @status = _('This e-mail address is available')
  225 + @status_class = 'available'
  226 + else
  227 + @status = _('This e-mail address is taken')
  228 + @status_class = 'unavailable'
  229 + end
  230 + render :partial => 'email_status'
  231 + end
  232 +
222 233 def user_data
223 234 user_data =
224 235 if logged_in?
... ... @@ -231,7 +242,7 @@ class AccountController &lt; ApplicationController
231 242 session[:notice] = nil # consume the notice
232 243 end
233 244  
234   - @plugins.enabled_plugins.each { |plugin| user_data.merge!(plugin.user_data_extras) }
  245 + @plugins.each { |plugin| user_data.merge!(plugin.user_data_extras) }
235 246  
236 247 render :text => user_data.to_json, :layout => false, :content_type => "application/javascript"
237 248 end
... ...
app/controllers/public/browse_controller.rb
... ... @@ -6,6 +6,8 @@ class BrowseController &lt; PublicController
6 6 more_recent
7 7 more_active
8 8 more_popular
  9 + more_comments
  10 + more_views
9 11 )
10 12  
11 13 def per_page
... ... @@ -36,6 +38,18 @@ class BrowseController &lt; PublicController
36 38 @results = @results.compact.paginate(:per_page => per_page, :page => params[:page])
37 39 end
38 40  
  41 + def contents
  42 + @filter = filter
  43 + @title = self.filter_description(params[:action] + '_' + @filter )
  44 +
  45 + @results = @environment.articles.published.text_articles.send(@filter)
  46 +
  47 + if !params[:query].blank?
  48 + @results = @results.find_by_contents(params[:query])
  49 + end
  50 + @results = @results.compact.paginate(:per_page => per_page, :page => params[:page])
  51 + end
  52 +
39 53 protected
40 54  
41 55 def filter
... ... @@ -54,6 +68,9 @@ class BrowseController &lt; PublicController
54 68 'communities_more_recent' => _('More recent communities'),
55 69 'communities_more_active' => _('More active communities'),
56 70 'communities_more_popular' => _('More popular communities'),
  71 + 'contents_more_recent' => _('More recent contents'),
  72 + 'contents_more_views' => _('Most viewed contents'),
  73 + 'contents_more_comments' => _('Most commented contents'),
57 74 }[str] || str
58 75 end
59 76  
... ...
app/controllers/public/catalog_controller.rb
... ... @@ -4,10 +4,11 @@ class CatalogController &lt; PublicController
4 4 before_filter :check_enterprise_and_environment
5 5  
6 6 def index
7   - @products = @profile.products.paginate(:per_page => 10, :page => params[:page])
  7 + @products = @profile.products.paginate(:order => 'name asc', :per_page => 9, :page => params[:page])
8 8 end
9 9  
10 10 protected
  11 +
11 12 def check_enterprise_and_environment
12 13 unless @profile.kind_of?(Enterprise) && !@profile.environment.enabled?('disable_products_for_enterprises')
13 14 redirect_to :controller => 'profile', :profile => profile.identifier, :action => 'index'
... ...
app/controllers/public/content_viewer_controller.rb
... ... @@ -31,14 +31,6 @@ class ContentViewerController &lt; ApplicationController
31 31 end
32 32 end
33 33  
34   - if !@page.public? && !request.ssl?
35   - return if redirect_to_ssl
36   - end
37   -
38   - if @page.public?
39   - return unless avoid_ssl
40   - end
41   -
42 34 if !@page.display_to?(user)
43 35 if profile.display_info_to?(user) || !profile.visible?
44 36 message = _('You are not allowed to view this content. You can contact the owner of this profile to request access then.')
... ... @@ -54,7 +46,7 @@ class ContentViewerController &lt; ApplicationController
54 46 return
55 47 end
56 48  
57   - redirect_to_translation
  49 + redirect_to_translation if @page.profile.redirect_l10n
58 50  
59 51 # At this point the page will be showed
60 52 @page.hit
... ... @@ -119,7 +111,11 @@ class ContentViewerController &lt; ApplicationController
119 111 def add_comment
120 112 @comment.author = user if logged_in?
121 113 @comment.article = @page
122   - if (logged_in? || @comment.reply_of_id || verify_recaptcha(:model => @comment, :message => _('Please type the words correctly'))) && @comment.save
  114 + @comment.ip_address = request.remote_ip
  115 + plugins_filter_comment(@comment)
  116 + return if @comment.rejected?
  117 + if (pass_without_comment_captcha? || verify_recaptcha(:model => @comment, :message => _('Please type the words correctly'))) && @comment.save
  118 + plugins_comment_saved(@comment)
123 119 @page.touch
124 120 @comment = nil # clear the comment form
125 121 redirect_to :action => 'view_page', :profile => params[:profile], :page => @page.explode_path, :view => params[:view]
... ... @@ -128,6 +124,23 @@ class ContentViewerController &lt; ApplicationController
128 124 end
129 125 end
130 126  
  127 + def plugins_filter_comment(comment)
  128 + @plugins.each do |plugin|
  129 + plugin.filter_comment(comment)
  130 + end
  131 + end
  132 +
  133 + def plugins_comment_saved(comment)
  134 + @plugins.each do |plugin|
  135 + plugin.comment_saved(comment)
  136 + end
  137 + end
  138 +
  139 + def pass_without_comment_captcha?
  140 + logged_in? && !environment.enabled?('captcha_for_logged_users')
  141 + end
  142 + helper_method :pass_without_comment_captcha?
  143 +
131 144 def remove_comment
132 145 @comment = @page.comments.find(params[:remove_comment])
133 146 if (user == @comment.author || user == @page.profile || user.has_permission?(:moderate_comments, @page.profile))
... ...
app/controllers/public/enterprise_registration_controller.rb
1 1 class EnterpriseRegistrationController < ApplicationController
2 2  
3   - require_ssl
4 3  
5 4 before_filter :login_required
6 5  
... ...
app/controllers/public/home_controller.rb
... ... @@ -14,4 +14,8 @@ class HomeController &lt; PublicController
14 14 end
15 15 end
16 16  
  17 + def terms
  18 + @no_design_blocks = true
  19 + end
  20 +
17 21 end
... ...
app/controllers/public/profile_controller.rb
... ... @@ -23,7 +23,7 @@ class ProfileController &lt; PublicController
23 23  
24 24 def tags
25 25 @tags_cache_key = "tags_profile_#{profile.id.to_s}"
26   - if is_cache_expired?(@tags_cache_key, true)
  26 + if is_cache_expired?(@tags_cache_key)
27 27 @tags = profile.article_tags
28 28 end
29 29 end
... ... @@ -31,7 +31,7 @@ class ProfileController &lt; PublicController
31 31 def content_tagged
32 32 @tag = params[:id]
33 33 @tag_cache_key = "tag_#{CGI.escape(@tag.to_s)}_#{profile.id.to_s}_page_#{params[:npage]}"
34   - if is_cache_expired?(@tag_cache_key, true)
  34 + if is_cache_expired?(@tag_cache_key)
35 35 @tagged = profile.find_tagged_with(@tag).paginate(:per_page => 20, :page => params[:npage])
36 36 end
37 37 end
... ... @@ -211,7 +211,8 @@ class ProfileController &lt; PublicController
211 211  
212 212 def remove_activity
213 213 begin
214   - activity = current_person.tracked_actions.find(params[:activity_id])
  214 + raise if !can_edit_profile
  215 + activity = ActionTracker::Record.find(params[:activity_id])
215 216 activity.destroy
216 217 render :text => _('Activity successfully removed.')
217 218 rescue
... ... @@ -219,6 +220,17 @@ class ProfileController &lt; PublicController
219 220 end
220 221 end
221 222  
  223 + def remove_notification
  224 + begin
  225 + raise if !can_edit_profile
  226 + notification = ActionTrackerNotification.find(:first, :conditions => {:profile_id => profile.id, :action_tracker_id => params[:activity_id]})
  227 + notification.destroy
  228 + render :text => _('Notification successfully removed.')
  229 + rescue
  230 + render :text => _('You could not remove this notification.')
  231 + end
  232 + end
  233 +
222 234 def profile_info
223 235 begin
224 236 @block = profile.blocks.find(params[:block_id])
... ... @@ -320,4 +332,8 @@ class ProfileController &lt; PublicController
320 332 20
321 333 end
322 334  
  335 + def can_edit_profile
  336 + @can_edit_profile ||= user && user.has_permission?('edit_profile', profile)
  337 + end
  338 + helper_method :can_edit_profile
323 339 end
... ...
app/controllers/public/search_controller.rb
... ... @@ -207,7 +207,7 @@ class SearchController &lt; PublicController
207 207  
208 208 def tags
209 209 @tags_cache_key = "tags_env_#{environment.id.to_s}"
210   - if is_cache_expired?(@tags_cache_key, true)
  210 + if is_cache_expired?(@tags_cache_key)
211 211 @tags = environment.tag_counts
212 212 end
213 213 end
... ... @@ -215,7 +215,7 @@ class SearchController &lt; PublicController
215 215 def tag
216 216 @tag = params[:tag]
217 217 @tag_cache_key = "tag_#{CGI.escape(@tag.to_s)}_env_#{environment.id.to_s}_page_#{params[:npage]}"
218   - if is_cache_expired?(@tag_cache_key, true)
  218 + if is_cache_expired?(@tag_cache_key)
219 219 @tagged = environment.articles.find_tagged_with(@tag).paginate(:per_page => 10, :page => params[:npage])
220 220 end
221 221 end
... ...
app/controllers/public_controller.rb
1 1 class PublicController < ApplicationController
2   - refuse_ssl
3 2 end
... ...
app/helpers/account_helper.rb
1 1 module AccountHelper
2 2  
  3 + def validation_classes
  4 + 'available unavailable valid invalid checking'
  5 + end
  6 +
  7 + def checking_message(key)
  8 + case key
  9 + when :url
  10 + _('Checking availability of login name...')
  11 + when :email
  12 + _('Checking if e-mail address is already taken...')
  13 + end
  14 + end
3 15 end
... ...
app/helpers/application_helper.rb
  1 +require 'redcloth'
  2 +
1 3 # Methods added to this helper will be available to all templates in the
2 4 # application.
3 5 module ApplicationHelper
... ... @@ -95,7 +97,7 @@ module ApplicationHelper
95 97 text = content_tag('div', button + content_tag('div', content_tag('div', content) + close_button, :class => 'help_message', :id => help_id, :style => 'display: none;'), :class => 'help_box')
96 98  
97 99 unless block.nil?
98   - concat(text, block.binding)
  100 + concat(text)
99 101 end
100 102  
101 103 text
... ... @@ -256,7 +258,7 @@ module ApplicationHelper
256 258 end
257 259  
258 260 def button_bar(options = {}, &block)
259   - concat(content_tag('div', capture(&block) + tag('br', :style => 'clear: left;'), { :class => 'button-bar' }.merge(options)), block.binding)
  261 + concat(content_tag('div', capture(&block) + tag('br', :style => 'clear: left;'), { :class => 'button-bar' }.merge(options)))
260 262 end
261 263  
262 264 VIEW_EXTENSIONS = %w[.rhtml .html.erb]
... ... @@ -538,7 +540,7 @@ module ApplicationHelper
538 540 {_('Members') => {:href => url_for(:controller => :profile, :action => :members, :profile => profile.identifier)}},
539 541 {_('Agenda') => {:href => url_for(:controller => :profile, :action => :events, :profile => profile.identifier)}},
540 542 {_('Join') => {:href => url_for(profile.join_url), :class => 'join-community', :style => 'display: none'}},
541   - {_('Leave') => {:href => url_for(profile.leave_url), :class => 'leave-community', :style => 'display: none'}},
  543 + {_('Leave community') => {:href => url_for(profile.leave_url), :class => 'leave-community', :style => 'display: none'}},
542 544 {_('Send an e-mail') => {:href => url_for(:profile => profile.identifier, :controller => 'contact', :action => 'new'), :class => 'send-an-email', :style => 'display: none'}}
543 545 ]
544 546 elsif profile.kind_of?(Enterprise)
... ... @@ -587,19 +589,20 @@ module ApplicationHelper
587 589  
588 590 def gravatar_url_for(email, options = {})
589 591 # Ta dando erro de roteamento
590   - url_for( { :gravatar_id => Digest::MD5.hexdigest(email),
  592 + default = theme_option['gravatar'] || NOOSFERO_CONF['gravatar'] || nil
  593 + url_for( { :gravatar_id => Digest::MD5.hexdigest(email.to_s),
591 594 :host => 'www.gravatar.com',
592 595 :protocol => 'http://',
593 596 :only_path => false,
594 597 :controller => 'avatar.php',
595   - :d => NOOSFERO_CONF['gravatar'] ? NOOSFERO_CONF['gravatar'] : nil
  598 + :d => default
596 599 }.merge(options) )
597 600 end
598 601  
599 602 def str_gravatar_url_for(email, options = {})
600   - default = NOOSFERO_CONF['gravatar'] ? NOOSFERO_CONF['gravatar'] : nil
  603 + default = theme_option['gravatar'] || NOOSFERO_CONF['gravatar'] || nil
601 604 url = 'http://www.gravatar.com/avatar.php?gravatar_id=' +
602   - Digest::MD5.hexdigest(email)
  605 + Digest::MD5.hexdigest(email.to_s)
603 606 {
604 607 :only_path => false,
605 608 :d => default
... ... @@ -609,6 +612,10 @@ module ApplicationHelper
609 612 url
610 613 end
611 614  
  615 + def gravatar_profile_url(email)
  616 + 'http://www.gravatar.com/'+ Digest::MD5.hexdigest(email.to_s)
  617 + end
  618 +
612 619 attr_reader :environment
613 620 def select_categories(object_name, title=nil, title_size=4)
614 621 return nil if environment.enabled?(:disable_categories)
... ... @@ -753,7 +760,7 @@ module ApplicationHelper
753 760  
754 761 # Should be on the forms_helper file but when its there the translation of labels doesn't work
755 762 class NoosferoFormBuilder < ActionView::Helpers::FormBuilder
756   - extend ActionView::Helpers::TagHelper
  763 + extend ActionView::Helpers::TagHelper
757 764  
758 765 def self.output_field(text, field_html, field_id = nil)
759 766 # try to guess an id if none given
... ... @@ -775,7 +782,7 @@ module ApplicationHelper
775 782 (field_helpers - %w(hidden_field)).each do |selector|
776 783 src = <<-END_SRC
777 784 def #{selector}(field, *args, &proc)
778   - text = object.class.human_attribute_name(field.to_s)
  785 + text = object.class.respond_to?(:human_attribute_name) && object.class.human_attribute_name(field.to_s) || field.to_s.humanize
779 786 NoosferoFormBuilder::output_field(text, super)
780 787 end
781 788 END_SRC
... ... @@ -877,7 +884,7 @@ module ApplicationHelper
877 884 end
878 885  
879 886 if block
880   - concat(result, block.binding)
  887 + concat(result)
881 888 end
882 889  
883 890 result
... ... @@ -909,18 +916,11 @@ module ApplicationHelper
909 916  
910 917 def login_url
911 918 options = Noosfero.url_options.merge({ :controller => 'account', :action => 'login' })
912   - if environment.enable_ssl && (ENV['RAILS_ENV'] != 'development')
913   - options.merge!(:protocol => 'https://', :host => ssl_hostname)
914   - end
915 919 url_for(options)
916 920 end
917 921  
918   - def ssl_hostname
919   - environment.default_hostname
920   - end
921   -
922 922 def base_url
923   - environment.top_url(request.ssl?)
  923 + environment.top_url
924 924 end
925 925  
926 926 def helper_for_article(article)
... ... @@ -985,7 +985,7 @@ module ApplicationHelper
985 985 'thickbox',
986 986 'lightbox',
987 987 'colorpicker',
988   - colorbox_stylesheet_path,
  988 + 'colorbox',
989 989 pngfix_stylesheet_path,
990 990 ] +
991 991 tokeninput_stylesheets
... ... @@ -1000,10 +1000,6 @@ module ApplicationHelper
1000 1000 'iepngfix/iepngfix.css'
1001 1001 end
1002 1002  
1003   - def colorbox_stylesheet_path
1004   - 'colorbox/colorbox.css'
1005   - end
1006   -
1007 1003 def tokeninput_stylesheets
1008 1004 ['token-input', 'token-input-facebook', 'token-input-mac']
1009 1005 end
... ... @@ -1024,7 +1020,7 @@ module ApplicationHelper
1024 1020 options.merge!(:page => params[:npage])
1025 1021 content = article.to_html(options)
1026 1022 content = content.kind_of?(Proc) ? self.instance_eval(&content) : content
1027   - @plugins && @plugins.enabled_plugins.each do |plugin|
  1023 + @plugins && @plugins.each do |plugin|
1028 1024 content = plugin.parse_content(content)
1029 1025 end
1030 1026 content
... ... @@ -1134,15 +1130,26 @@ module ApplicationHelper
1134 1130 link_to(content_tag(:span, _('Communities Menu')), '#', :onclick => "toggleSubmenu(this,'',#{links.to_json}); return false", :class => 'menu-submenu-trigger up', :id => 'submenu-communities-trigger')
1135 1131 end
1136 1132  
  1133 + def browse_contents_menu
  1134 + links = [
  1135 + {s_('contents|More Comments') => {:href => url_for({:controller => 'browse', :action => 'contents', :filter => 'more_comments'})}},
  1136 + {s_('contents|More Views') => {:href => url_for({:controller => 'browse', :action => 'contents', :filter => 'more_views'})}},
  1137 + {s_('contents|More Recent') => {:href => url_for({:controller => 'browse', :action => 'contents', :filter => 'more_recent'})}}
  1138 + ]
  1139 +
  1140 + link_to(content_tag(:span, _('Contents'), :class => 'icon-blog'), {:controller => "browse", :action => 'contents'}, :id => 'submenu-contents') +
  1141 + link_to(content_tag(:span, _('Contents Menu')), '#', :onclick => "toggleSubmenu(this,'',#{links.to_json}); return false", :class => 'menu-submenu-trigger up', :id => 'submenu-contents-trigger')
  1142 + end
  1143 +
1137 1144 def pagination_links(collection, options={})
1138   - options = {:prev_label => '&laquo; ' + _('Previous'), :next_label => _('Next') + ' &raquo;'}.merge(options)
  1145 + options = {:previous_label => '&laquo; ' + _('Previous'), :next_label => _('Next') + ' &raquo;'}.merge(options)
1139 1146 will_paginate(collection, options)
1140 1147 end
1141 1148  
1142 1149 def render_environment_features(folder)
1143 1150 result = ''
1144 1151 environment.enabled_features.keys.each do |feature|
1145   - file = File.join(@controller.view_paths, 'shared', folder.to_s, "#{feature}.rhtml")
  1152 + file = File.join(@controller.view_paths.last, 'shared', folder.to_s, "#{feature}.rhtml")
1146 1153 if File.exists?(file)
1147 1154 result << render(:file => file, :use_full_path => false)
1148 1155 end
... ... @@ -1166,7 +1173,7 @@ module ApplicationHelper
1166 1173 pending_tasks_count = link_to(count.to_s, @environment.top_url + '/myprofile/{login}/tasks', :id => 'pending-tasks-count', :title => _("Manage your pending tasks"))
1167 1174 end
1168 1175  
1169   - (_('Welcome, %s') % link_to('<i></i><strong>{login}</strong>', @environment.top_url + '/{login}', :id => "homepage-link", :title => _('Go to your homepage'))) +
  1176 + (_("<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'))) +
1170 1177 render_environment_features(:usermenu) +
1171 1178 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') +
1172 1179 manage_enterprises.to_s +
... ... @@ -1226,7 +1233,7 @@ module ApplicationHelper
1226 1233 wrapper = content_tag(:div, capture(&block), :class => 'comment-balloon-content')
1227 1234 (1..8).to_a.reverse.each { |i| wrapper = content_tag(:div, wrapper, :class => "comment-wrapper-#{i}") }
1228 1235 classes = options.delete(:class) || options.delete("class") || ''
1229   - concat(content_tag('div', wrapper + tag('br', :style => 'clear: both;'), { :class => 'comment-balloon ' + classes.to_s }.merge(options)), block.binding)
  1236 + concat(content_tag('div', wrapper + tag('br', :style => 'clear: both;'), { :class => 'comment-balloon ' + classes.to_s }.merge(options)))
1230 1237 end
1231 1238  
1232 1239 def display_source_info(page)
... ... @@ -1247,25 +1254,27 @@ module ApplicationHelper
1247 1254 task.information[:message] % values
1248 1255 end
1249 1256  
  1257 + def add_zoom_to_article_images
  1258 + add_zoom_to_images if environment.enabled?(:show_zoom_button_on_article_images)
  1259 + end
  1260 +
1250 1261 def add_zoom_to_images
1251   - if environment.enabled?(:show_zoom_button_on_article_images)
1252   - stylesheet_link_tag('fancybox') +
1253   - javascript_include_tag('jquery.fancybox-1.3.4.pack') +
1254   - javascript_tag("jQuery(function($) {
1255   - $(window).load( function() {
1256   - $('#article .article-body img').each( function(index) {
1257   - var original = original_image_dimensions($(this).attr('src'));
1258   - if ($(this).width() < original['width'] || $(this).height() < original['height']) {
1259   - $(this).wrap('<div class=\"zoomable-image\" />');
1260   - $(this).parent('.zoomable-image').attr('style', $(this).attr('style'));
1261   - $(this).attr('style', '');
1262   - $(this).after(\'<a href=\"' + $(this).attr('src') + '\" class=\"zoomify-image\"><span class=\"zoomify-text\">%s</span></a>');
1263   - }
1264   - });
1265   - $('.zoomify-image').fancybox();
  1262 + stylesheet_link_tag('fancybox') +
  1263 + javascript_include_tag('jquery.fancybox-1.3.4.pack') +
  1264 + javascript_tag("jQuery(function($) {
  1265 + $(window).load( function() {
  1266 + $('#article .article-body img').each( function(index) {
  1267 + var original = original_image_dimensions($(this).attr('src'));
  1268 + if ($(this).width() < original['width'] || $(this).height() < original['height']) {
  1269 + $(this).wrap('<div class=\"zoomable-image\" />');
  1270 + $(this).parent('.zoomable-image').attr('style', $(this).attr('style'));
  1271 + $(this).attr('style', '');
  1272 + $(this).after(\'<a href=\"' + $(this).attr('src') + '\" class=\"zoomify-image\"><span class=\"zoomify-text\">%s</span></a>');
  1273 + }
1266 1274 });
1267   - });" % _('Zoom in'))
1268   - end
  1275 + $('.zoomify-image').fancybox();
  1276 + });
  1277 + });" % _('Zoom in'))
1269 1278 end
1270 1279  
1271 1280 def render_dialog_error_messages(instance_name)
... ... @@ -1303,4 +1312,29 @@ module ApplicationHelper
1303 1312 ) + content_tag('span', ' | ', :class => 'comment-footer comment-footer-hide')
1304 1313 end
1305 1314 end
  1315 +
  1316 + def cache_timeout(key, timeout, &block)
  1317 + cache(key, { :expires_in => timeout }, &block)
  1318 + end
  1319 +
  1320 + def is_cache_expired?(key)
  1321 + !cache_store.fetch(ActiveSupport::Cache.expand_cache_key(key, :controller))
  1322 + end
  1323 +
  1324 + def render_tabs(tabs)
  1325 + titles = tabs.inject(''){ |result, tab| result << content_tag(:li, link_to(tab[:title], '#'+tab[:id]), :class => 'tab') }
  1326 + contents = tabs.inject(''){ |result, tab| result << content_tag(:div, tab[:content], :id => tab[:id]) }
  1327 +
  1328 + content_tag :div, :class => 'ui-tabs' do
  1329 + content_tag(:ul, titles) + contents
  1330 + end
  1331 + end
  1332 +
  1333 + def delete_article_message(article)
  1334 + if article.folder?
  1335 + _("Are you sure that you want to remove the folder \"#{article.name}\"? Note that all the items inside it will also be removed!")
  1336 + else
  1337 + _("Are you sure that you want to remove the item \"#{article.name}\"?")
  1338 + end
  1339 + end
1306 1340 end
... ...
app/helpers/blog_helper.rb
... ... @@ -17,7 +17,7 @@ module BlogHelper
17 17 def list_posts(articles, format = 'full')
18 18 pagination = will_paginate(articles, {
19 19 :param_name => 'npage',
20   - :prev_label => _('&laquo; Newer posts'),
  20 + :previous_label => _('&laquo; Newer posts'),
21 21 :next_label => _('Older posts &raquo;')
22 22 })
23 23 content = []
... ...
app/helpers/boxes_helper.rb
... ... @@ -81,8 +81,8 @@ module BoxesHelper
81 81 box_decorator == DontMoveBlocks
82 82 end
83 83  
84   - def display_block_content(block, main_content = nil)
85   - content = block.main? ? wrap_main_content(main_content) : block.content
  84 + def display_block_content(block, person, main_content = nil)
  85 + content = block.main? ? wrap_main_content(main_content) : block.content({:person => person})
86 86 result = extract_block_content(content)
87 87 footer_content = extract_block_content(block.footer)
88 88 unless footer_content.blank?
... ... @@ -99,7 +99,7 @@ module BoxesHelper
99 99 unless block.visible?
100 100 options[:title] = _("This block is invisible. Your visitors will not see it.")
101 101 end
102   - @controller.send(:content_editor?) || @plugins.enabled_plugins.each do |plugin|
  102 + @controller.send(:content_editor?) || @plugins.each do |plugin|
103 103 result = plugin.parse_content(result)
104 104 end
105 105 box_decorator.block_target(block.box, block) +
... ...
app/helpers/catalog_helper.rb
1 1 module CatalogHelper
2 2  
3   -include DisplayHelper
4   -include ManageProductsHelper
  3 + include DisplayHelper
  4 + include ManageProductsHelper
5 5  
6   - def display_products_list(profile, products)
7   - data = ''
8   - extra_content = []
9   - extra_content_list = []
10   - products.each { |product|
11   - extra_content = @plugins.map(:catalog_item_extras, product).collect { |content| instance_eval(&content) } if @plugins
12   - extra_content_list = @plugins.map(:catalog_list_item_extras, product).collect { |content| instance_eval(&content) } if @plugins
13   - data << content_tag('li',
14   - link_to_product(product, :class => 'product-pic', :style => 'background-image:url(%s)' % product.default_image(:portrait) ) +
15   - content_tag('h3', link_to_product(product)) +
16   - content_tag('ul',
17   - (product.price ? content_tag('li', _('Price: %s') % ( "%.2f" % product.price), :class => 'product_price') : '') +
18   - content_tag('li', product_category_name(profile, product.product_category), :class => 'product_category') +
19   - extra_content_list.map { |content| content_tag('li', content)}.join("\n")
20   - ) +
21   - (product.description ? content_tag('div',
22   - txt2html(product.description),
23   - :class => 'description') : tag('br',
24   - :style => 'clear:both')) +
25   - extra_content.join("\n"),
26   - :class => 'product')
27   - }
28   - content_tag('h1', _('Products/Services')) + content_tag('ul', data, :id => 'product_list')
29   - end
30   -
31   - private
32   -
33   - def product_category_name(profile, product_category)
34   - if profile.enabled?
35   - link_to_product_category(product_category)
36   - else
37   - product_category ? product_category.full_name(' &rarr; ') : _('Uncategorized product')
38   - end
39   - end
40 6 end
... ...
app/helpers/cms_helper.rb
... ... @@ -16,7 +16,7 @@ module CmsHelper
16 16 end
17 17  
18 18 def pagination_links(collection, options={})
19   - options = {:prev_label => '&laquo; ', :next_label => ' &raquo;', :page_links => false}.merge(options)
  19 + options = {:previous_label => '&laquo; ', :next_label => ' &raquo;', :page_links => false}.merge(options)
20 20 will_paginate(collection, options)
21 21 end
22 22  
... ... @@ -49,12 +49,6 @@ module CmsHelper
49 49 end
50 50  
51 51 def display_delete_button(article)
52   - confirm_message = if article.folder?
53   - _('Are you sure that you want to remove this folder? Note that all the items inside it will also be removed!')
54   - else
55   - _('Are you sure that you want to remove this item?')
56   - end
57   -
58   - button_without_text :delete, _('Delete'), { :action => 'destroy', :id => article.id }, :method => :post, :confirm => confirm_message
  52 + button_without_text :delete, _('Delete'), { :action => 'destroy', :id => article.id }, :method => :post, :confirm => delete_article_message(article)
59 53 end
60 54 end
... ...
app/helpers/content_viewer_helper.rb
... ... @@ -55,7 +55,7 @@ module ContentViewerHelper
55 55 "http://www.facebook.com/sharer.php?s=100&p[title]=%{title}&p[summary]=%{summary}&p[url]=%{url}&p[images][0]=%{image}" % {
56 56 :title => CGI.escape(article.title),
57 57 :url => CGI.escape(url_for(article.url)),
58   - :summary => CGI.escape(truncate(strip_tags(article.body.to_s), 300)),
  58 + :summary => CGI.escape(truncate(strip_tags(article.body.to_s), :length => 300)),
59 59 :image => CGI.escape(article.body_images_paths.first.to_s)
60 60 }
61 61 end
... ...
app/helpers/dates_helper.rb
... ... @@ -42,11 +42,11 @@ module DatesHelper
42 42 end
43 43 end
44 44  
45   - def show_period(date1, date2 = nil)
  45 + def show_period(date1, date2 = nil, use_numbers = false)
46 46 if (date1 == date2) || (date2.nil?)
47   - show_date(date1)
  47 + show_date(date1, use_numbers)
48 48 else
49   - _('from %{date1} to %{date2}') % {:date1 => show_date(date1), :date2 => show_date(date2)}
  49 + _('from %{date1} to %{date2}') % {:date1 => show_date(date1, use_numbers), :date2 => show_date(date2, use_numbers)}
50 50 end
51 51 end
52 52  
... ...
app/helpers/display_helper.rb
... ... @@ -8,6 +8,20 @@ module DisplayHelper
8 8 opts
9 9 end
10 10  
  11 + def image_link_to_product(product, opts={})
  12 + return _('No product') unless product
  13 + target = product_path(product)
  14 + link_to image_tag(product.default_image(:big), :alt => product.name),
  15 + target,
  16 + opts
  17 + end
  18 +
  19 + def price_span(price, options = {})
  20 + content_tag 'span',
  21 + number_to_currency(price, :unit => environment.currency_unit, :delimiter => environment.currency_delimiter, :separator => environment.currency_separator),
  22 + options
  23 + end
  24 +
11 25 def product_path(product)
12 26 product.enterprise.enabled? ? product.enterprise.public_profile_url.merge(:controller => 'manage_products', :action => 'show', :id => product) : product.enterprise.url
13 27 end
... ...
app/helpers/forms_helper.rb
... ... @@ -14,9 +14,9 @@ module FormsHelper
14 14  
15 15 def labelled_check_box( human_name, name, value = "1", checked = false, options = {} )
16 16 options[:id] ||= 'checkbox-' + FormsHelper.next_id_number
17   - check_box_tag( name, value, checked, options ) +
18   - content_tag( 'label', human_name, :for => options[:id] ) +
19   - hidden_field_tag(name, '0')
  17 + hidden_field_tag(name, '0') +
  18 + check_box_tag( name, value, checked, options ) +
  19 + content_tag( 'label', human_name, :for => options[:id] )
20 20 end
21 21  
22 22 def labelled_text_field( human_name, name, value=nil, options={} )
... ...
app/helpers/forum_helper.rb
... ... @@ -11,7 +11,7 @@ module ForumHelper
11 11 def list_forum_posts(articles)
12 12 pagination = will_paginate(articles, {
13 13 :param_name => 'npage',
14   - :prev_label => _('&laquo; Newer posts'),
  14 + :previous_label => _('&laquo; Newer posts'),
15 15 :next_label => _('Older posts &raquo;')
16 16 })
17 17 content = [content_tag('tr',
... ...
app/helpers/manage_products_helper.rb
... ... @@ -55,7 +55,7 @@ module ManageProductsHelper
55 55 def options_for_select_categories(categories, selected = nil)
56 56 categories.sort_by{|cat| cat.name.transliterate}.map do |category|
57 57 selected_attribute = selected.nil? ? '' : (category == selected ? "selected='selected'" : '')
58   - "<option value='#{category.id}' title='#{category.name}' #{selected_attribute}>#{truncate(category.name, 33) + (category.leaf? ? '': ' &raquo;')}</option>"
  58 + "<option value='#{category.id}' title='#{category.name}' #{selected_attribute}>#{truncate(category.name, :length => 33) + (category.leaf? ? '': ' &raquo;')}</option>"
59 59 end.join("\n")
60 60 end
61 61  
... ... @@ -271,4 +271,23 @@ module ManageProductsHelper
271 271 return input_amount_used if input.unit.blank?
272 272 n_('1 %{singular_unit}', '%{num} %{plural_unit}', input.amount_used.to_f) % { :num => input_amount_used, :singular_unit => content_tag('span', input.unit.singular, :class => 'input-unit'), :plural_unit => content_tag('span', input.unit.plural, :class => 'input-unit') }
273 273 end
  274 +
  275 + def select_production_cost(product,selected=nil)
  276 + url = url_for( :controller => 'manage_products', :action => 'create_production_cost' )
  277 + prompt_msg = _('Insert the name of the new cost:')
  278 + error_msg = _('Something went wrong. Please, try again')
  279 + select_tag('price_details[][production_cost_id]',
  280 + '<option value="" disabled="disabled">' + _('Select...') + '</option>' +
  281 + options_for_select(product.available_production_costs.map {|item| [truncate(item.name, 10, '...'), item.id]} + [[_('Other cost'), '']], selected),
  282 + {:class => 'production-cost-selection',
  283 + :onchange => "productionCostTypeChange(this, '#{url}', '#{prompt_msg}', '#{error_msg}')"})
  284 + end
  285 +
  286 + def price_composition_progressbar_text(product, args = {})
  287 + currency = environment.currency_unit
  288 + production_cost = args[:production_cost_value] || product.formatted_value(:total_production_cost)
  289 + product_price = args[:product_price] || product.formatted_value(:price)
  290 +
  291 + _("%{currency} %{production_cost} of %{currency} %{product_price}") % {:currency => currency, :production_cost => content_tag('span', production_cost, :class => 'production_cost'), :product_price => content_tag('span', product_price, :class => 'product_price')}
  292 + end
274 293 end
... ...
app/helpers/profile_editor_helper.rb
... ... @@ -137,8 +137,8 @@ module ProfileEditorHelper
137 137 content_tag(
138 138 'div',
139 139 capture(&block) + '<br style="clear:left;"/>&nbsp;',
140   - :class => 'control-panel'),
141   - block.binding)
  140 + :class => 'control-panel')
  141 + )
142 142 end
143 143  
144 144 def control_panel_button(title, icon, url)
... ...
app/helpers/profile_helper.rb
... ... @@ -15,12 +15,4 @@ module ProfileHelper
15 15 end
16 16 end
17 17  
18   - def render_tabs(tabs)
19   - titles = tabs.inject(''){ |result, tab| result << content_tag(:li, link_to(tab[:title], '#'+tab[:id]), :class => 'tab') }
20   - contents = tabs.inject(''){ |result, tab| result << content_tag(:div, tab[:content], :id => tab[:id]) }
21   -
22   - content_tag :div, :class => 'ui-tabs' do
23   - content_tag(:ul, titles) + contents
24   - end
25   - end
26 18 end
... ...
app/helpers/sweeper_helper.rb
... ... @@ -4,9 +4,7 @@ module SweeperHelper
4 4 ActionController::Base.new().expire_fragment(*args)
5 5 end
6 6  
7   - def expire_timeout_fragment(*args)
8   - ActionController::Base.new().expire_timeout_fragment(*args)
9   - end
  7 + alias :expire_timeout_fragment :expire_fragment
10 8  
11 9 def expire_friends(profile)
12 10 # public friends page
... ... @@ -22,7 +20,7 @@ module SweeperHelper
22 20  
23 21 # friends blocks
24 22 blocks = profile.blocks.select{|b| b.kind_of?(FriendsBlock)}
25   - blocks.map(&:cache_key).each{|ck|expire_timeout_fragment(ck)}
  23 + BlockSweeper.expire_blocks(blocks)
26 24 end
27 25  
28 26 def expire_communities(profile)
... ... @@ -34,13 +32,13 @@ module SweeperHelper
34 32  
35 33 # communities block
36 34 blocks = profile.blocks.select{|b| b.kind_of?(CommunitiesBlock)}
37   - blocks.map(&:cache_key).each{|ck|expire_timeout_fragment(ck)}
  35 + BlockSweeper.expire_blocks(blocks)
38 36 end
39 37  
40 38 def expire_enterprises(profile)
41 39 # enterprises and favorite enterprises blocks
42 40 blocks = profile.blocks.select {|b| [EnterprisesBlock, FavoriteEnterprisesBlock].any?{|klass| b.kind_of?(klass)} }
43   - blocks.map(&:cache_key).each{|ck|expire_timeout_fragment(ck)}
  41 + BlockSweeper.expire_blocks(blocks)
44 42 end
45 43  
46 44 def expire_profile_index(profile)
... ...
app/helpers/tags_helper.rb
... ... @@ -50,7 +50,7 @@ module TagsHelper
50 50 style = ""+
51 51 "font-size: #{ (v * delta).round + min_size }px;"+
52 52 "top: #{ -(delta/2) - (v * (delta/2)).round }px;"
53   - destination = url.kind_of?(Hash) ? url_for(url.merge(tagname_option => tag)) : (url.to_s + tag)
  53 + destination = url.merge(tagname_option => tag)
54 54  
55 55 if options[:show_count]
56 56 display_count = options[:show_count] ? "<small><sup>(#{count})</sup></small>" : ""
... ...
app/models/add_member.rb
... ... @@ -11,7 +11,9 @@ class AddMember &lt; Task
11 11 settings_items :roles
12 12  
13 13 def perform
14   - self.roles ||= [Profile::Roles.member(organization.environment.id).id]
  14 + if !self.roles or (self.roles.uniq.compact.length == 1 and self.roles.uniq.compact.first.to_i.zero?)
  15 + self.roles = [Profile::Roles.member(organization.environment.id).id]
  16 + end
15 17 target.affiliate(requestor, self.roles.select{|r| !r.to_i.zero? }.map{|i| Role.find(i)})
16 18 end
17 19  
... ...
app/models/article.rb
... ... @@ -13,7 +13,7 @@ class Article &lt; ActiveRecord::Base
13 13 validates_presence_of :profile_id, :name
14 14 validates_presence_of :slug, :path, :if => lambda { |article| !article.name.blank? }
15 15  
16   - validates_uniqueness_of :slug, :scope => ['profile_id', 'parent_id'], :message => N_('<!-- %{fn} -->The title (article name) is already being used by another article, please use another title.'), :if => lambda { |article| !article.slug.blank? }
  16 + validates_uniqueness_of :slug, :scope => ['profile_id', 'parent_id'], :message => N_('The title (article name) is already being used by another article, please use another title.'), :if => lambda { |article| !article.slug.blank? }
17 17  
18 18 belongs_to :last_changed_by, :class_name => 'Person', :foreign_key => 'last_changed_by_id'
19 19  
... ... @@ -34,7 +34,7 @@ class Article &lt; ActiveRecord::Base
34 34 before_destroy :rotate_translations
35 35  
36 36 before_create do |article|
37   - article.published_at = article.created_at if article.published_at.nil?
  37 + article.published_at ||= Time.now
38 38 if article.reference_article && !article.parent
39 39 parent = article.reference_article.parent
40 40 if parent && parent.blog? && article.profile.has_blog?
... ... @@ -233,7 +233,7 @@ class Article &lt; ActiveRecord::Base
233 233  
234 234 include ActionView::Helpers::TextHelper
235 235 def short_title
236   - truncate self.title, 15, '...'
  236 + truncate self.title, :length => 15, :omission => '...'
237 237 end
238 238  
239 239 def belongs_to_blog?
... ... @@ -355,11 +355,20 @@ class Article &lt; ActiveRecord::Base
355 355 ['Folder', 'Blog', 'Forum', 'Gallery']
356 356 end
357 357  
  358 + def self.text_article_types
  359 + ['TextArticle', 'TextileArticle', 'TinyMceArticle']
  360 + end
  361 +
358 362 named_scope :published, :conditions => { :published => true }
359 363 named_scope :folders, :conditions => { :type => folder_types}
360 364 named_scope :no_folders, :conditions => ['type NOT IN (?)', folder_types]
361 365 named_scope :galleries, :conditions => { :type => 'Gallery' }
362 366 named_scope :images, :conditions => { :is_image => true }
  367 + named_scope :text_articles, :conditions => [ 'articles.type IN (?)', text_article_types ]
  368 +
  369 + named_scope :more_comments, :order => "comments_count DESC"
  370 + named_scope :more_views, :order => "hits DESC"
  371 + named_scope :more_recent, :order => "created_at DESC"
363 372  
364 373 def self.display_filter(user, profile)
365 374 return {:conditions => ['published = ?', true]} if !user
... ... @@ -487,8 +496,8 @@ class Article &lt; ActiveRecord::Base
487 496 end
488 497  
489 498 alias :active_record_cache_key :cache_key
490   - def cache_key(params = {}, the_profile = nil)
491   - active_record_cache_key +
  499 + def cache_key(params = {}, the_profile = nil, language = 'en')
  500 + active_record_cache_key+'-'+language +
492 501 (allow_post_content?(the_profile) ? "-owner" : '') +
493 502 (params[:npage] ? "-npage-#{params[:npage]}" : '') +
494 503 (params[:year] ? "-year-#{params[:year]}" : '') +
... ... @@ -505,7 +514,7 @@ class Article &lt; ActiveRecord::Base
505 514 end
506 515  
507 516 def short_lead
508   - truncate sanitize_html(self.lead), 170, '...'
  517 + truncate sanitize_html(self.lead), :length => 170, :omission => '...'
509 518 end
510 519  
511 520 def creator
... ... @@ -528,6 +537,28 @@ class Article &lt; ActiveRecord::Base
528 537 end
529 538 end
530 539  
  540 + def more_comments_label
  541 + amount = self.comments_count
  542 + {
  543 + 0 => _('no comments'),
  544 + 1 => _('one comment')
  545 + }[amount] || _("%s comments") % amount
  546 +
  547 + end
  548 +
  549 + def more_views_label
  550 + amount = self.hits
  551 + {
  552 + 0 => _('no views'),
  553 + 1 => _('one view')
  554 + }[amount] || _("%s views") % amount
  555 +
  556 + end
  557 +
  558 + def more_recent_label
  559 + _('Created at: ')
  560 + end
  561 +
531 562 private
532 563  
533 564 def sanitize_tag_list
... ...
app/models/article_block.rb
... ... @@ -8,7 +8,7 @@ class ArticleBlock &lt; Block
8 8 _('This block displays one of your articles. You can edit the block to select which one of your articles is going to be displayed in the block.')
9 9 end
10 10  
11   - def content
  11 + def content(args={})
12 12 block = self
13 13 lambda do
14 14 block_title(block.title) +
... ...
app/models/block.rb
... ... @@ -81,7 +81,7 @@ class Block &lt; ActiveRecord::Base
81 81 # The method can also return <tt>nil</tt>, which means "no content".
82 82 #
83 83 # See BoxesHelper#extract_block_content for implementation details.
84   - def content
  84 + def content(args={})
85 85 "This is block number %d" % self.id
86 86 end
87 87  
... ... @@ -127,6 +127,11 @@ class Block &lt; ActiveRecord::Base
127 127 true
128 128 end
129 129  
  130 + alias :active_record_cache_key :cache_key
  131 + def cache_key(language='en')
  132 + active_record_cache_key+'-'+language
  133 + end
  134 +
130 135 def timeout
131 136 4.hours
132 137 end
... ...
app/models/blog.rb
... ... @@ -68,7 +68,7 @@ class Blog &lt; Folder
68 68 settings_items :visualization_format, :type => :string, :default => 'full'
69 69 validates_inclusion_of :visualization_format, :in => [ 'full', 'short' ], :if => :visualization_format
70 70  
71   - settings_items :display_posts_in_current_language, :type => :boolean, :default => true
  71 + settings_items :display_posts_in_current_language, :type => :boolean, :default => false
72 72  
73 73 alias :display_posts_in_current_language? :display_posts_in_current_language
74 74  
... ...
app/models/blog_archives_block.rb
... ... @@ -20,11 +20,15 @@ class BlogArchivesBlock &lt; Block
20 20 blog_id && owner.blogs.exists?(blog_id) ? owner.blogs.find(blog_id) : owner.blog
21 21 end
22 22  
23   - def content
  23 + def visible_posts(person)
  24 + blog.posts.native_translations.select {|post| post.display_to?(person)}
  25 + end
  26 +
  27 + def content(args={})
24 28 owner_blog = self.blog
25 29 return nil unless owner_blog
26 30 results = ''
27   - owner_blog.posts.native_translations.group_by {|i| i.published_at.year }.sort_by { |year,count| -year }.each do |year, results_by_year|
  31 + visible_posts(args[:person]).group_by {|i| i.published_at.year }.sort_by { |year,count| -year }.each do |year, results_by_year|
28 32 results << content_tag('li', content_tag('strong', "#{year} (#{results_by_year.size})"))
29 33 results << "<ul class='#{year}-archive'>"
30 34 results_by_year.group_by{|i| [ ('%02d' % i.published_at.month()), gettext(MONTHS[i.published_at.month() - 1])]}.sort.reverse.each do |month, results_by_month|
... ...
app/models/categories_block.rb
... ... @@ -28,7 +28,7 @@ class CategoriesBlock &lt; Block
28 28 Category.top_level_for(self.owner).from_types(self.category_types)
29 29 end
30 30  
31   - def content
  31 + def content(args={})
32 32 block = self
33 33 lambda do
34 34 render :file => 'blocks/categories', :locals => { :block => block }
... ...
app/models/category.rb
1 1 class Category < ActiveRecord::Base
2 2  
3   - validates_exclusion_of :slug, :in => [ 'index' ], :message => N_('%{fn} cannot be like that.')
  3 + validates_exclusion_of :slug, :in => [ 'index' ], :message => N_('%{fn} cannot be like that.').fix_i18n
4 4 validates_presence_of :name, :environment_id
5   - validates_uniqueness_of :slug,:scope => [ :environment_id, :parent_id ], :message => N_('%{fn} is already being used by another category.')
  5 + validates_uniqueness_of :slug,:scope => [ :environment_id, :parent_id ], :message => N_('%{fn} is already being used by another category.').fix_i18n
6 6 belongs_to :environment
7 7  
8 8 validates_inclusion_of :display_color, :in => [ 1, 2, 3, 4, nil ]
9   - validates_uniqueness_of :display_color, :scope => :environment_id, :if => (lambda { |cat| ! cat.display_color.nil? }), :message => N_('%{fn} was already assigned to another category.')
  9 + 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
10 10  
11 11 # Finds all top level categories for a given environment.
12 12 named_scope :top_level_for, lambda { |environment|
... ...
app/models/change_password.rb
... ... @@ -30,10 +30,10 @@ class ChangePassword &lt; Task
30 30 unless data.login.blank? || data.email.blank?
31 31 user = User.find_by_login_and_environment_id(data.login, data.environment_id)
32 32 if user.nil?
33   - data.errors.add(:login, _('%{fn} is not a valid username.'))
  33 + data.errors.add(:login, _('%{fn} is not a valid username.').fix_i18n)
34 34 else
35 35 if user.email != data.email
36   - data.errors.add(:email, _('%{fn} is invalid.'))
  36 + data.errors.add(:email)
37 37 end
38 38 end
39 39 end
... ...
app/models/comment.rb
... ... @@ -2,7 +2,7 @@ class Comment &lt; ActiveRecord::Base
2 2  
3 3 track_actions :leave_comment, :after_create, :keep_params => ["article.title", "article.url", "title", "url", "body"], :custom_target => :action_tracker_target
4 4  
5   - validates_presence_of :title, :body
  5 + validates_presence_of :body
6 6 belongs_to :article, :counter_cache => true
7 7 belongs_to :author, :class_name => 'Person', :foreign_key => 'author_id'
8 8 has_many :children, :class_name => 'Comment', :foreign_key => 'reply_of_id', :dependent => :destroy
... ... @@ -17,7 +17,7 @@ class Comment &lt; ActiveRecord::Base
17 17 validates_presence_of :author_id, :if => (lambda { |rec| rec.name.blank? && rec.email.blank? })
18 18 validates_each :name do |rec,attribute,value|
19 19 if rec.author_id && (!rec.name.blank? || !rec.email.blank?)
20   - rec.errors.add(:name, _('%{fn} can only be informed for unauthenticated authors'))
  20 + rec.errors.add(:name, _('%{fn} can only be informed for unauthenticated authors').fix_i18n)
21 21 end
22 22 end
23 23  
... ... @@ -126,4 +126,12 @@ class Comment &lt; ActiveRecord::Base
126 126 end
127 127 end
128 128  
  129 + def rejected?
  130 + @rejected
  131 + end
  132 +
  133 + def reject!
  134 + @rejected = true
  135 + end
  136 +
129 137 end
... ...
app/models/community.rb
... ... @@ -34,7 +34,7 @@ class Community &lt; Organization
34 34 super
35 35 self.required_fields.each do |field|
36 36 if self.send(field).blank?
37   - self.errors.add(field, _('%{fn} can\'t be blank'))
  37 + self.errors.add_on_blank(field)
38 38 end
39 39 end
40 40 end
... ...
app/models/create_community.rb
... ... @@ -16,7 +16,7 @@ class CreateCommunity &lt; Task
16 16 def validate
17 17 self.environment.required_community_fields.each do |field|
18 18 if self.send(field).blank?
19   - self.errors.add(field, _('%{fn} can\'t be blank'))
  19 + self.errors.add_on_blank(field)
20 20 end
21 21 end
22 22 end
... ...
app/models/create_enterprise.rb
... ... @@ -40,12 +40,12 @@ class CreateEnterprise &lt; Task
40 40  
41 41 if self.region && self.target
42 42 unless self.region.validators.include?(self.target) || self.target_type == "Environment"
43   - self.errors.add(:target, '%{fn} is not a validator for the chosen region')
  43 + self.errors.add(:target, _('%{fn} is not a validator for the chosen region').fix_i18n)
44 44 end
45 45 end
46 46  
47 47 if self.status != Task::Status::CANCELLED && self.identifier && Profile.exists?(:identifier => self.identifier)
48   - self.errors.add(:identifier, '%{fn} is already being as identifier by another enterprise, organization or person.')
  48 + self.errors.add(:identifier, _('%{fn} is already being as identifier by another enterprise, organization or person.').fix_i18n)
49 49 end
50 50 end
51 51  
... ...
app/models/disabled_enterprise_message_block.rb
... ... @@ -12,7 +12,7 @@ class DisabledEnterpriseMessageBlock &lt; Block
12 12 _('Message')
13 13 end
14 14  
15   - def content
  15 + def content(args={})
16 16 message = self.owner.environment.message_for_disabled_enterprise || ''
17 17 lambda do
18 18 render :file => 'blocks/disabled_enterprise_message', :locals => {:message => message}
... ...
app/models/domain.rb
... ... @@ -10,14 +10,14 @@ class Domain &lt; ActiveRecord::Base
10 10  
11 11 # <tt>name</tt> must be a sequence of word characters (a to z, plus 0 to 9,
12 12 # plus '_'). Letters must be lowercase
13   - validates_format_of :name, :with => /^([a-z0-9_-]+\.)+[a-z0-9_-]+$/, :message => N_('%{fn} must be composed only of lowercase latters (a to z), numbers (0 to 9), "_" and "-"')
  13 + validates_format_of :name, :with => /^([a-z0-9_-]+\.)+[a-z0-9_-]+$/, :message => N_('%{fn} must be composed only of lowercase latters (a to z), numbers (0 to 9), "_" and "-"').fix_i18n
14 14  
15 15 # checks validations that could not be expressed using Rails' predefined
16 16 # validations. In particular:
17 17 # * <tt>name</tt> must not start with 'www.'
18 18 def validate
19 19 if self.name =~ /^www\./
20   - self.errors.add(:name, _('%{fn} must not start with www.'))
  20 + self.errors.add(:name, _('%{fn} must not start with www.').fix_i18n)
21 21 end
22 22 end
23 23  
... ...
app/models/enterprise.rb
... ... @@ -6,6 +6,7 @@ class Enterprise &lt; Organization
6 6  
7 7 has_many :products, :dependent => :destroy, :order => 'name ASC'
8 8 has_many :inputs, :through => :products
  9 + has_many :production_costs, :as => :owner
9 10  
10 11 has_and_belongs_to_many :fans, :class_name => 'Person', :join_table => 'favorite_enteprises_people'
11 12  
... ... @@ -45,7 +46,7 @@ class Enterprise &lt; Organization
45 46 super
46 47 self.required_fields.each do |field|
47 48 if self.send(field).blank?
48   - self.errors.add(field, _("%{fn} can't be blank"))
  49 + self.errors.add_on_blank(field)
49 50 end
50 51 end
51 52 end
... ... @@ -75,7 +76,11 @@ class Enterprise &lt; Organization
75 76 end
76 77  
77 78 after_save do |e|
78   - e.products.each{ |p| p.enterprise_updated(e) }
  79 + e.delay.update_products_position
  80 + end
  81 +
  82 + def update_products_position
  83 + products.each{ |p| p.enterprise_updated(self) }
79 84 end
80 85  
81 86 def closed?
... ...
app/models/enterprise_homepage.rb
... ... @@ -12,18 +12,13 @@ class EnterpriseHomepage &lt; Article
12 12 profile.nil? ? _('Homepage') : profile.name
13 13 end
14 14  
15   - # FIXME isn't this too much including just to be able to generate some HTML?
16   - include ActionView::Helpers::TagHelper
17   - include ActionView::Helpers::UrlHelper
18   - include ActionController::UrlWriter
19   - include ActionView::Helpers::AssetTagHelper
20   - include EnterpriseHomepageHelper
21   - include CatalogHelper
22   -
23   - def to_html(options ={})
24   - products = self.profile.products
25   - display_profile_info(self.profile) + content_tag('div', self.body || '') +
26   - (self.profile.environment.enabled?('disable_products_for_enterprises') ? '' : display_products_list(self.profile, products))
  15 + def to_html(options = {})
  16 + enterprise_homepage = self
  17 + lambda do
  18 + extend EnterpriseHomepageHelper
  19 + @products = profile.products.paginate(:order => 'id asc', :per_page => 9, :page => 1)
  20 + render :partial => 'content_viewer/enterprise_homepage', :object => enterprise_homepage
  21 + end
27 22 end
28 23  
29 24 def can_display_hits?
... ...
app/models/environment.rb
... ... @@ -120,7 +120,8 @@ class Environment &lt; ActiveRecord::Base
120 120 'enterprises_are_validated_when_created' => __('Enterprises are validated when created'),
121 121 'show_balloon_with_profile_links_when_clicked' => _('Show a balloon with profile links when a profile image is clicked'),
122 122 'xmpp_chat' => _('XMPP/Jabber based chat'),
123   - 'show_zoom_button_on_article_images' => _('Show a zoom link on all article images')
  123 + 'show_zoom_button_on_article_images' => _('Show a zoom link on all article images'),
  124 + 'captcha_for_logged_users' => _('Ask captcha when a logged user comments too'),
124 125 }
125 126 end
126 127  
... ... @@ -174,6 +175,7 @@ class Environment &lt; ActiveRecord::Base
174 175 acts_as_accessible
175 176  
176 177 has_many :units, :order => 'position'
  178 + has_many :production_costs, :as => :owner
177 179  
178 180 def superior_intances
179 181 [self, nil]
... ... @@ -221,7 +223,6 @@ class Environment &lt; ActiveRecord::Base
221 223 settings_items :layout_template, :type => String, :default => 'default'
222 224 settings_items :homepage, :type => String
223 225 settings_items :description, :type => String, :default => '<div style="text-align: center"><a href="http://noosfero.org/"><img src="/images/noosfero-network.png" alt="Noosfero"/></a></div>'
224   - settings_items :enable_ssl
225 226 settings_items :local_docs, :type => Array, :default => []
226 227 settings_items :news_amount_by_folder, :type => Integer, :default => 4
227 228 settings_items :help_message_to_add_enterprise, :type => String, :default => ''
... ... @@ -562,8 +563,8 @@ class Environment &lt; ActiveRecord::Base
562 563 domain
563 564 end
564 565  
565   - def top_url(ssl = false)
566   - protocol = (ssl ? 'https' : 'http')
  566 + def top_url
  567 + protocol = 'http'
567 568 result = "#{protocol}://#{default_hostname}"
568 569 if Noosfero.url_options.has_key?(:port)
569 570 result << ':' << Noosfero.url_options[:port].to_s
... ...
app/models/environment_finder.rb
... ... @@ -53,7 +53,7 @@ class EnvironmentFinder
53 53 # SECURITY no risk of SQL injection, since product_category_ids comes from trusted source
54 54 @environment.send(asset).find_by_contents(query, ferret_options, options.merge({:include => 'product_categorizations', :conditions => 'product_categorizations.category_id = (%s)' % product_category.id }))
55 55 elsif product_category && asset == :enterprises
56   - @environment.send(asset).find_by_contents(query, ferret_options, options.merge(:joins => 'inner join product_categorizations on (product_categorizations.product_id = products.id)', :include => 'products', :conditions => "product_categorizations.category_id = (#{product_category.id})"))
  56 + @environment.send(asset).find_by_contents(query, ferret_options, options.merge(:joins => 'inner join products on products.enterprise_id = profiles.id inner join product_categorizations on (product_categorizations.product_id = products.id)', :conditions => "product_categorizations.category_id = (#{product_category.id})"))
57 57 else
58 58 @environment.send(asset).find_by_contents(query, ferret_options, options)
59 59 end
... ...
app/models/environment_statistics_block.rb
... ... @@ -12,7 +12,7 @@ class EnvironmentStatisticsBlock &lt; Block
12 12 _('This block presents some statistics about your environment.')
13 13 end
14 14  
15   - def content
  15 + def content(args={})
16 16 users = owner.people.visible.count
17 17 enterprises = owner.enterprises.visible.count
18 18 communities = owner.communities.visible.count
... ...
app/models/event.rb
... ... @@ -22,7 +22,7 @@ class Event &lt; Article
22 22  
23 23 validates_each :start_date do |event,field,value|
24 24 if event.end_date && event.start_date && event.start_date > event.end_date
25   - event.errors.add(:start_date, _('%{fn} cannot come before end date.'))
  25 + event.errors.add(:start_date, _('%{fn} cannot come before end date.').fix_i18n)
26 26 end
27 27 end
28 28  
... ...
app/models/featured_products_block.rb
... ... @@ -25,7 +25,7 @@ class FeaturedProductsBlock &lt; Block
25 25 self.owner.highlighted_products_with_image
26 26 end
27 27  
28   - def content
  28 + def content(args={})
29 29 block = self
30 30 lambda do
31 31 render :file => 'blocks/featured_products', :locals => { :block => block }
... ...
app/models/feed_reader_block.rb
... ... @@ -13,6 +13,7 @@ class FeedReaderBlock &lt; Block
13 13 old_address = address
14 14 orig_set_address(new_address)
15 15 self.enabled = (new_address && new_address != old_address) || (new_address && self.enabled) || false
  16 + self.fetched_at = nil
16 17 end
17 18  
18 19 settings_items :limit, :type => :integer
... ... @@ -71,12 +72,13 @@ class FeedReaderBlock &lt; Block
71 72 self.feed_title = nil
72 73 self.error_message = nil
73 74 end
  75 +
74 76 def finish_fetch
75 77 self.fetched_at = Time.now
76 78 self.save!
77 79 end
78 80  
79   - def content
  81 + def content(args={})
80 82 block_title(title) + formatted_feed_content
81 83 end
82 84  
... ...
app/models/highlights_block.rb
... ... @@ -28,7 +28,7 @@ class HighlightsBlock &lt; Block
28 28 shuffle ? block_images.shuffle : block_images
29 29 end
30 30  
31   - def content
  31 + def content(args={})
32 32 block = self
33 33 lambda do
34 34 render :file => 'blocks/highlights', :locals => { :block => block }
... ...
app/models/image.rb
... ... @@ -9,15 +9,15 @@ class Image &lt; ActiveRecord::Base
9 9 has_attachment :content_type => :image,
10 10 :storage => :file_system,
11 11 :path_prefix => 'public/image_uploads',
12   - :resize_to => '320x200>',
  12 + :resize_to => '800x600>',
13 13 :thumbnails => { :big => '150x150',
14 14 :thumb => '100x100',
15 15 :portrait => '64x64',
16 16 :minor => '50x50',
17 17 :icon => '20x20!' },
18   - :max_size => 500.kilobytes # 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 500.0 KB")
  20 + validates_attachment :size => N_("%{fn} of uploaded file was larger than the maximum size of 5.0 MB").fix_i18n
21 21  
22 22 delay_attachment_fu_thumbnails
23 23  
... ...
app/models/input.rb
... ... @@ -45,6 +45,18 @@ class Input &lt; ActiveRecord::Base
45 45 %w[price_per_unit amount_used].each do |field|
46 46 return true unless self.send(field).blank?
47 47 end
48   - return false
  48 + false
  49 + end
  50 +
  51 + def has_all_price_details?
  52 + %w[price_per_unit unit amount_used].each do |field|
  53 + return false if self.send(field).blank?
  54 + end
  55 + true
  56 + end
  57 +
  58 + def cost
  59 + return 0 if self.amount_used.blank? || self.price_per_unit.blank?
  60 + self.amount_used * self.price_per_unit
49 61 end
50 62 end
... ...
app/models/link_list_block.rb
... ... @@ -47,7 +47,7 @@ class LinkListBlock &lt; Block
47 47 _('This block can be used to create a menu of links. You can add, remove and update the links as you wish.')
48 48 end
49 49  
50   - def content
  50 + def content(args={})
51 51 block_title(title) +
52 52 content_tag('ul',
53 53 links.select{|i| !i[:name].blank? and !i[:address].blank?}.map{|i| content_tag('li', link_html(i))}
... ...
app/models/location_block.rb
... ... @@ -11,7 +11,7 @@ class LocationBlock &lt; Block
11 11 _('Shows where the profile is on the material world.')
12 12 end
13 13  
14   - def content
  14 + def content(args={})
15 15 profile = self.owner
16 16 title = self.title
17 17 if profile.lat
... ...
app/models/login_block.rb
... ... @@ -8,7 +8,7 @@ class LoginBlock &lt; Block
8 8 _('This block presents a login/logout block.')
9 9 end
10 10  
11   - def content
  11 + def content(args={})
12 12 lambda do
13 13 render :file => 'blocks/login_block'
14 14 end
... ...
app/models/main_block.rb
... ... @@ -8,7 +8,7 @@ class MainBlock &lt; Block
8 8 _('This block presents the main content of your pages.')
9 9 end
10 10  
11   - def content
  11 + def content(args={})
12 12 nil
13 13 end
14 14  
... ...
app/models/my_network_block.rb
... ... @@ -14,7 +14,7 @@ class MyNetworkBlock &lt; Block
14 14 _('This block displays some info about your networking.')
15 15 end
16 16  
17   - def content
  17 + def content(args={})
18 18 block = self
19 19 lambda do
20 20 render :file => 'blocks/my_network', :locals => {
... ...
app/models/organization.rb
... ... @@ -157,4 +157,8 @@ class Organization &lt; Profile
157 157 members_by_role(role).map { |member| {:id => member.id, :name => member.name} }.to_json
158 158 end
159 159  
  160 + def disable
  161 + self.visible = false
  162 + save!
  163 + end
160 164 end
... ...
app/models/person.rb
... ... @@ -116,10 +116,17 @@ class Person &lt; Profile
116 116 contact_phone
117 117 contact_information
118 118 description
  119 + image
119 120 ]
120 121  
121 122 validates_multiparameter_assignments
122 123  
  124 + validates_each :birth_date do |record,attr,value|
  125 + if value && value.year == 1
  126 + record.errors.add(attr)
  127 + end
  128 + end
  129 +
123 130 def self.fields
124 131 FIELDS
125 132 end
... ... @@ -129,7 +136,7 @@ class Person &lt; Profile
129 136 self.required_fields.each do |field|
130 137 if self.send(field).blank?
131 138 unless (field == 'custom_area_of_study' && self.area_of_study != 'Others') || (field == 'custom_formation' && self.formation != 'Others')
132   - self.errors.add(field, _('%{fn} is mandatory'))
  139 + self.errors.add_on_blank(field)
133 140 end
134 141 end
135 142 end
... ... @@ -191,7 +198,7 @@ class Person &lt; Profile
191 198  
192 199 validates_each :email, :on => :update do |record,attr,value|
193 200 if User.find(:first, :conditions => ['email = ? and id != ? and environment_id = ?', value, record.user.id, record.environment.id])
194   - record.errors.add(attr, _('%{fn} is already used by other user'))
  201 + record.errors.add(attr, _('%{fn} is already used by other user').fix_i18n)
195 202 end
196 203 end
197 204  
... ... @@ -403,7 +410,15 @@ class Person &lt; Profile
403 410 end
404 411  
405 412 def control_panel_settings_button
406   - {:title => _('Profile Info and settings'), :icon => 'edit-profile'}
  413 + {:title => _('Edit Profile'), :icon => 'edit-profile'}
  414 + end
  415 +
  416 + def disable
  417 + self.visible = false
  418 + user.password = Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{identifier}--")
  419 + user.password_confirmation = user.password
  420 + save!
  421 + user.save!
407 422 end
408 423  
409 424 protected
... ...
app/models/price_detail.rb 0 → 100644
... ... @@ -0,0 +1,27 @@
  1 +class PriceDetail < ActiveRecord::Base
  2 +
  3 + belongs_to :product
  4 + validates_presence_of :product_id
  5 +
  6 + belongs_to :production_cost
  7 + validates_presence_of :production_cost_id
  8 + validates_uniqueness_of :production_cost_id, :scope => :product_id
  9 +
  10 + def price
  11 + self[:price] || 0
  12 + end
  13 +
  14 + include FloatHelper
  15 + def price=(value)
  16 + if value.is_a?(String)
  17 + super(decimal_to_float(value))
  18 + else
  19 + super(value)
  20 + end
  21 + end
  22 +
  23 + def formatted_value(value)
  24 + ("%.2f" % self[value]).to_s.gsub('.', product.enterprise.environment.currency_separator) if self[value]
  25 + end
  26 +
  27 +end
... ...
app/models/product.rb
... ... @@ -5,6 +5,8 @@ class Product &lt; ActiveRecord::Base
5 5 has_many :product_qualifiers
6 6 has_many :qualifiers, :through => :product_qualifiers
7 7 has_many :inputs, :dependent => :destroy, :order => 'position'
  8 + has_many :price_details, :dependent => :destroy
  9 + has_many :production_costs, :through => :price_details
8 10  
9 11 validates_uniqueness_of :name, :scope => :enterprise_id, :allow_nil => true
10 12 validates_presence_of :product_category_id
... ... @@ -101,12 +103,13 @@ class Product &lt; ActiveRecord::Base
101 103 enterprise.public_profile
102 104 end
103 105  
104   - def formatted_value(value)
105   - ("%.2f" % self[value]).to_s.gsub('.', enterprise.environment.currency_separator) if self[value]
  106 + def formatted_value(method)
  107 + value = self[method] || self.send(method)
  108 + ("%.2f" % value).to_s.gsub('.', enterprise.environment.currency_separator) if value
106 109 end
107 110  
108 111 def price_with_discount
109   - price - discount if discount
  112 + discount ? (price - discount) : price
110 113 end
111 114  
112 115 def price=(value)
... ... @@ -125,6 +128,23 @@ class Product &lt; ActiveRecord::Base
125 128 end
126 129 end
127 130  
  131 + # Note: will probably be completely overhauled for AI1413
  132 + def inputs_prices?
  133 + return false if self.inputs.count <= 0
  134 + self.inputs.each do |input|
  135 + return false if input.has_price_details? == false
  136 + end
  137 + true
  138 + end
  139 +
  140 + def any_inputs_details?
  141 + return false if self.inputs.count <= 0
  142 + self.inputs.each do |input|
  143 + return true if input.has_all_price_details? == true
  144 + end
  145 + false
  146 + end
  147 +
128 148 def has_basic_info?
129 149 %w[unit price discount].each do |field|
130 150 return true if !self.send(field).blank?
... ... @@ -153,4 +173,44 @@ class Product &lt; ActiveRecord::Base
153 173 true
154 174 end
155 175  
  176 + def inputs_cost
  177 + return 0 if inputs.empty?
  178 + inputs.map(&:cost).inject { |sum,price| sum + price }
  179 + end
  180 +
  181 + def total_production_cost
  182 + return inputs_cost if price_details.empty?
  183 + inputs_cost + price_details.map(&:price).inject { |sum,price| sum + price }
  184 + end
  185 +
  186 + def price_described?
  187 + return false if price.blank? or price == 0
  188 + (price - total_production_cost).zero?
  189 + end
  190 +
  191 + def update_price_details(price_details)
  192 + self.price_details.destroy_all
  193 + price_details.each do |price_detail|
  194 + self.price_details.create(price_detail)
  195 + end
  196 + end
  197 +
  198 + def price_description_percentage
  199 + return 0 if price.blank? || price.zero?
  200 + total_production_cost * 100 / price
  201 + end
  202 +
  203 + def available_production_costs
  204 + self.enterprise.environment.production_costs + self.enterprise.production_costs
  205 + end
  206 +
  207 + include ActionController::UrlWriter
  208 + def price_composition_bar_display_url
  209 + url_for({:host => enterprise.default_hostname, :controller => 'manage_products', :action => 'display_price_composition_bar', :profile => enterprise.identifier, :id => self.id }.merge(Noosfero.url_options))
  210 + end
  211 +
  212 + def inputs_cost_update_url
  213 + url_for({:host => enterprise.default_hostname, :controller => 'manage_products', :action => 'display_inputs_cost', :profile => enterprise.identifier, :id => self.id }.merge(Noosfero.url_options))
  214 + end
  215 +
156 216 end
... ...
app/models/production_cost.rb 0 → 100644
... ... @@ -0,0 +1,8 @@
  1 +class ProductionCost < ActiveRecord::Base
  2 +
  3 + belongs_to :owner, :polymorphic => true
  4 + validates_presence_of :owner
  5 + validates_presence_of :name
  6 + validates_length_of :name, :maximum => 30, :allow_blank => true
  7 + validates_uniqueness_of :name, :scope => [:owner_id, :owner_type]
  8 +end
... ...
app/models/products_block.rb
... ... @@ -16,7 +16,7 @@ class ProductsBlock &lt; Block
16 16 _('This block presents a list of your products.')
17 17 end
18 18  
19   - def content
  19 + def content(args={})
20 20 block_title(title) +
21 21 content_tag(
22 22 'ul',
... ...
app/models/profile.rb
... ... @@ -20,12 +20,16 @@ class Profile &lt; ActiveRecord::Base
20 20 find_role('editor', env_id)
21 21 end
22 22 def self.organization_member_roles(env_id)
23   - [admin(env_id), moderator(env_id), member(env_id)]
  23 + all_roles(env_id).select{ |r| r.key.match(/^profile_/) unless r.key.blank? }
24 24 end
25 25 def self.all_roles(env_id)
26   - [admin(env_id), member(env_id), moderator(env_id), owner(env_id), editor(env_id)]
  26 + Role.all :conditions => { :environment_id => env_id }
  27 + end
  28 + def self.method_missing(m, *args, &block)
  29 + role = find_role(m, args[0])
  30 + return role unless role.nil?
  31 + super
27 32 end
28   -
29 33 private
30 34 def self.find_role(name, env_id)
31 35 ::Role.find_by_key_and_environment_id("profile_#{name}", env_id)
... ... @@ -115,6 +119,7 @@ class Profile &lt; ActiveRecord::Base
115 119  
116 120 acts_as_having_settings :field => :data
117 121  
  122 + settings_items :redirect_l10n, :type => :boolean, :default => false
118 123 settings_items :public_content, :type => :boolean, :default => true
119 124 settings_items :description
120 125  
... ... @@ -147,6 +152,7 @@ class Profile &lt; ActiveRecord::Base
147 152 doc
148 153 chat
149 154 plugin
  155 + site
150 156 ]
151 157  
152 158 belongs_to :user
... ... @@ -609,7 +615,7 @@ private :generate_url, :url_options
609 615 include ActionView::Helpers::TextHelper
610 616 def short_name(chars = 40)
611 617 if self[:nickname].blank?
612   - truncate self.name, chars, '...'
  618 + truncate self.name, :length => chars, :omission => '...'
613 619 else
614 620 self[:nickname]
615 621 end
... ... @@ -806,15 +812,10 @@ private :generate_url, :url_options
806 812 end
807 813  
808 814 def disable
809   - self.visible = false
810   - user.password = Digest::SHA1.hexdigest("--#{Time.now.to_s}--#{identifier}--")
811   - user.password_confirmation = user.password
812   - save!
813   - user.save!
814 815 end
815 816  
816 817 def control_panel_settings_button
817   - {:title => _('Profile Info and settings'), :icon => 'edit-profile'}
  818 + {:title => _('Edit Profile'), :icon => 'edit-profile'}
818 819 end
819 820  
820 821 def self.identification
... ...
app/models/profile_image_block.rb
... ... @@ -10,7 +10,7 @@ class ProfileImageBlock &lt; Block
10 10 _('This block presents the profile image')
11 11 end
12 12  
13   - def content
  13 + def content(args={})
14 14 block = self
15 15 s = show_name
16 16 lambda do
... ...
app/models/profile_info_block.rb
... ... @@ -8,7 +8,7 @@ class ProfileInfoBlock &lt; Block
8 8 _('Basic information about <i>%{user}</i>: how long <i>%{user}</i> is part of <i>%{env}</i> and useful links.') % { :user => self.owner.name(), :env => self.owner.environment.name() }
9 9 end
10 10  
11   - def content
  11 + def content(args={})
12 12 block = self
13 13 lambda do
14 14 render :file => 'blocks/profile_info', :locals => { :block => block }
... ...
app/models/profile_list_block.rb
... ... @@ -37,7 +37,7 @@ class ProfileListBlock &lt; Block
37 37 _('Clicking on the people or groups will take you to their home page.')
38 38 end
39 39  
40   - def content
  40 + def content(args={})
41 41 profiles = self.profile_list
42 42 title = self.view_title
43 43 nl = "\n"
... ...
app/models/profile_search_block.rb
... ... @@ -4,7 +4,7 @@ class ProfileSearchBlock &lt; Block
4 4 _('Display a form to search the profile')
5 5 end
6 6  
7   - def content
  7 + def content(args={})
8 8 title = self.title
9 9 lambda do
10 10 render :file => 'blocks/profile_search', :locals => { :title => title }
... ...
app/models/raw_html_block.rb
... ... @@ -6,7 +6,7 @@ class RawHTMLBlock &lt; Block
6 6  
7 7 settings_items :html, :type => :text
8 8  
9   - def content
  9 + def content(args={})
10 10 (title.blank? ? '' : block_title(title)) + html.to_s
11 11 end
12 12  
... ...
app/models/recent_documents_block.rb
... ... @@ -15,7 +15,7 @@ class RecentDocumentsBlock &lt; Block
15 15 settings_items :limit, :type => :integer, :default => 5
16 16  
17 17 include ActionController::UrlWriter
18   - def content
  18 + def content(args={})
19 19 docs = self.limit.nil? ? owner.recent_documents : owner.recent_documents(self.limit)
20 20  
21 21 block_title(title) +
... ...
app/models/sellers_search_block.rb
... ... @@ -16,7 +16,7 @@ class SellersSearchBlock &lt; Block
16 16 _('This block presents a search engine for products.')
17 17 end
18 18  
19   - def content
  19 + def content(args={})
20 20 title = self.title
21 21 lambda do
22 22 render :file => 'search/_sellers_form', :locals => { :title => title }
... ...
app/models/slideshow_block.rb
... ... @@ -31,7 +31,7 @@ class SlideshowBlock &lt; Block
31 31 gallery.images.reject {|item| item.folder?}
32 32 end
33 33  
34   - def content
  34 + def content(args={})
35 35 block = self
36 36 if gallery
37 37 images = block_images
... ...
app/models/tags_block.rb
... ... @@ -19,7 +19,7 @@ class TagsBlock &lt; Block
19 19 Try to add some tags to some articles and you'l see your tag cloud growing.")
20 20 end
21 21  
22   - def content
  22 + def content(args={})
23 23 tags = owner.article_tags
24 24 return '' if tags.empty?
25 25  
... ...
app/models/theme.rb
... ... @@ -43,8 +43,11 @@ class Theme
43 43  
44 44 def approved_themes(owner)
45 45 Dir.glob(File.join(system_themes_dir, '*')).select do |item|
46   - config = YAML.load_file(File.join(item, 'theme.yml'))
47   - (config['owner_type'] == owner.class.base_class.name) && (config['owner_id'] == owner.id) || config['public']
  46 + if File.exists?( File.join(item, 'theme.yml') )
  47 + config = YAML.load_file(File.join(item, 'theme.yml'))
  48 + (config['owner_type'] == owner.class.base_class.name) &&
  49 + (config['owner_id'] == owner.id) || config['public']
  50 + end
48 51 end.map do |desc|
49 52 new(File.basename(desc))
50 53 end
... ...
app/models/uploaded_file.rb
... ... @@ -50,7 +50,7 @@ class UploadedFile &lt; Article
50 50 :thumbnail_class => Thumbnail,
51 51 :max_size => 5.megabytes # remember to update validate message below
52 52  
53   - validates_attachment :size => N_("%{fn} of uploaded file was larger than the maximum size of 5.0 MB")
  53 + validates_attachment :size => N_("%{fn} of uploaded file was larger than the maximum size of 5.0 MB").fix_i18n
54 54  
55 55 delay_attachment_fu_thumbnails
56 56  
... ...
app/models/user.rb
... ... @@ -100,7 +100,7 @@ class User &lt; ActiveRecord::Base
100 100 before_save :encrypt_password
101 101 validates_format_of :email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => (lambda {|user| !user.email.blank?})
102 102  
103   - 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.')
  103 + 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
104 104  
105 105 # Authenticates a user by their login name and unencrypted password. Returns the user or nil.
106 106 def self.authenticate(login, password, environment = nil)
... ...
app/sweepers/article_sweeper.rb
... ... @@ -13,15 +13,11 @@ class ArticleSweeper &lt; ActiveRecord::Observer
13 13 protected
14 14  
15 15 def expire_caches(article)
16   - article.hierarchy.each do |a|
17   - if a != article
18   - a.touch
19   - end
20   - end
  16 + article.hierarchy.each { |a| a.touch if a != article }
21 17 blocks = article.profile.blocks
22 18 blocks += article.profile.environment.blocks if article.profile.environment
23 19 blocks = blocks.select{|b|[RecentDocumentsBlock, BlogArchivesBlock].any?{|c| b.kind_of?(c)}}
24   - blocks.map(&:cache_key).each{|ck|expire_timeout_fragment(ck)}
  20 + BlockSweeper.expire_blocks(blocks)
25 21 env = article.profile.environment
26 22 if env && (env.portal_community == article.profile)
27 23 expire_fragment(env.portal_news_cache_key)
... ...
app/sweepers/block_sweeper.rb 0 → 100644
... ... @@ -0,0 +1,28 @@
  1 +class BlockSweeper < ActiveRecord::Observer
  2 +
  3 + observe :block
  4 +
  5 + class << self
  6 + include SweeperHelper
  7 +
  8 + def cache_key_regex(block)
  9 + regex = '-[a-z]*$'
  10 + clean_ck = block.cache_key.gsub(/#{regex}/,'')
  11 + %r{#{clean_ck+regex}}
  12 + end
  13 +
  14 + # Expire block's all languages cache
  15 + def expire_block(block)
  16 + expire_timeout_fragment(cache_key_regex(block))
  17 + end
  18 +
  19 + def expire_blocks(blocks)
  20 + blocks.each { |block| expire_block(block) }
  21 + end
  22 + end
  23 +
  24 + def after_save(block)
  25 + self.class.expire_block(block)
  26 + end
  27 +
  28 +end
... ...
app/sweepers/friendship_sweeper.rb
... ... @@ -35,7 +35,7 @@ protected
35 35 end
36 36  
37 37 blocks = profile.blocks.select{|b| b.kind_of?(FriendsBlock)}
38   - blocks.map(&:cache_key).each{|ck|expire_timeout_fragment(ck)}
  38 + BlockSweeper.expire_blocks(blocks)
39 39 end
40 40  
41 41 end
... ...
app/sweepers/profile_sweeper.rb
... ... @@ -31,7 +31,7 @@ protected
31 31  
32 32 def expire_statistics_block_cache(profile)
33 33 blocks = profile.environment.blocks.select { |b| b.kind_of?(EnvironmentStatisticsBlock) }
34   - blocks.map(&:cache_key).each{|ck|expire_timeout_fragment(ck)}
  34 + BlockSweeper.expire_blocks(blocks)
35 35 end
36 36  
37 37 def expire_blogs(profile)
... ...
app/sweepers/role_assignment_sweeper.rb
... ... @@ -25,7 +25,7 @@ protected
25 25  
26 26 profile.blocks_to_expire_cache.each { |block|
27 27 blocks = profile.blocks.select{|b| b.kind_of?(block)}
28   - blocks.map(&:cache_key).each{|ck|expire_timeout_fragment(ck)}
  28 + BlockSweeper.expire_blocks(blocks)
29 29 }
30 30 end
31 31  
... ...
app/views/account/_email_status.rhtml 0 → 100644
... ... @@ -0,0 +1,7 @@
  1 +<div class='status-identifier'>
  2 + <p><span class='<%= @status_class %>'><%= @status %></span></p>
  3 + <script type="text/javascript">
  4 + jQuery('#user_email').removeClass('<%= validation_classes %>');
  5 + jQuery('#user_email').addClass('<%= @status_class %>');
  6 + </script>
  7 +</div>
... ...
app/views/account/_identifier_status.rhtml
1 1 <div class='status-identifier'>
2   - <p><%= @url %> <span class='<%= @status_class %>'><%= @status %></span> </p>
  2 + <p><span class='<%= @status_class %>'><%= @status %></span></p>
  3 + <script type="text/javascript">
  4 + jQuery('#user_login').removeClass('<%= validation_classes %>');
  5 + jQuery('#user_login').addClass('<%= @status_class %>');
  6 + </script>
3 7 </div>
... ...
app/views/account/_signup_form.rhtml
1 1 <%= error_messages_for :user, :person %>
2 2  
3   -<% if ! defined? hidden_atention || ! hidden_atention %>
4   -<p/>
5   -<div class="atention">
6   -<%= _('Dear user, welcome to the %s network. To start your participation in this space, fill in the fields below. After this operation, your login and password will be registered, allowing you to create %s and %s in this environment.') % [environment.name, __('communities'), __('enterprises')] %>
7   -</div>
8   -<% end %>
9   -
10   -<% labelled_form_for :user, @user, :html => { :multipart => true } do |f| %>
  3 +<% labelled_form_for :user, @user, :html => { :multipart => true, :id => 'signup-form' } do |f| %>
11 4  
12 5 <%= hidden_field_tag :invitation_code, @invitation_code %>
13 6  
14   -<%= required_fields_message %>
  7 +<div id='signup-form-header'>
15 8  
16   -<div id='signup-email'>
17   - <%= required f.text_field(:email) %>
18   - <%= content_tag(:small,_('This e-mail address will be used to contact you.')) %>
19   -</div>
  9 + <span id="signup-domain"><%= environment.default_hostname %>/</span>
  10 + <div id='signup-login'>
  11 + <div id='signup-login-field'>
  12 + <%= required f.text_field(:login, :onchange => 'this.value = convToValidLogin(this.value);', :rel => s_('signup|Login')) %>
  13 + <div id='url-check'><p>&nbsp;</p></div>
  14 + </div>
  15 + <%= content_tag(:small, _('Choose your login name carefully! It will be your network access and you will not be able to change it later.'), :id => 'signup-balloon') %>
  16 + <br style="clear: both;" />
  17 + </div>
  18 + <%= observe_field 'user_login',
  19 + :url => { :action => 'check_url' },
  20 + :with => 'identifier',
  21 + :update => 'url-check',
  22 + :loading => "jQuery('#user_login').removeClass('#{validation_classes}').addClass('checking');
  23 + jQuery('#url-check').html('<p><span class=\"checking\">#{checking_message(:url)}</span></p>');",
  24 + :complete => "jQuery('#user_login').removeClass('checking')"
  25 + %>
20 26  
21   -<%= required f.text_field(:login, :onchange => 'this.value = convToValidLogin( this.value )') %>
22   -<%= content_tag(:small,_('Insert your login')) %>
23   -<div id='url-check'></div>
  27 + <div id='signup-password'>
  28 + <%= required f.password_field(:password, :id => 'user_pw') %>
  29 + <%= f.text_field(:password_clear, :value => _('password')) %>
  30 + <%= content_tag(:small,_('Choose a password that you can remember easily. It must have at least 4 characters.'), :id => 'password-balloon') %>
  31 + <div id='fake-check'><p>&nbsp;</p></div>
  32 + </div>
  33 +
  34 + <div id='signup-password-confirmation'>
  35 + <%= required f.password_field(:password_confirmation) %>
  36 + <%= f.text_field(:password_confirmation_clear, :value => _('password confirmation')) %>
  37 + <div id='password-check'><p>&nbsp;</p></div>
  38 + </div>
  39 +
  40 + <div id='signup-email'>
  41 + <%= required f.text_field(:email, :rel => _('e-Mail')) %>
  42 + <%= content_tag(:small,_('This e-mail address will be used to contact you.')) %>
  43 + <div id='email-check'><p>&nbsp;</p></div>
  44 + </div>
  45 + <%= observe_field "user_email",
  46 + :url => { :action => "check_email" },
  47 + :with => "address",
  48 + :update => "email-check",
  49 + :loading => "jQuery('#user_email').removeClass('#{validation_classes}').addClass('checking');
  50 + jQuery('#email-check').html('<p><span class=\"checking\">#{checking_message(:email)}</span></p>');",
  51 + :complete => "jQuery('#user_email').removeClass('checking')",
  52 + :before => "if (!( jQuery('#user_email').valid() )) {
  53 + jQuery('#user_email').removeClass('#{validation_classes}').addClass('unavailable');
  54 + jQuery('#email-check').html('<p><span class=\"unavailable\">#{_('This e-mail address is not valid')}</span></p>');
  55 + return false;
  56 + }"
  57 + %>
24 58  
25   -<%= observe_field 'user_login', :url => {:action => 'check_url'}, :with => 'identifier', :update => 'url-check' %>
  59 + <%= label :profile_data, :name %>
  60 + <%= required text_field(:profile_data, :name, :rel => _('Full name')) %>
26 61  
27   -<div id='signup-password'>
28   - <%= required f.password_field(:password) %>
29   - <%= content_tag(:small,_('Choose a password that you can remember easily. It must have at least 4 characters.')) %>
30 62 </div>
31 63  
32   -<%= required f.password_field(:password_confirmation) %>
33   -<%= content_tag(:small,_('To confirm, repeat your password.')) %>
34   -
35   -<% labelled_fields_for :profile_data, @person do |f| %>
36   - <%= render :partial => 'profile_editor/person_form', :locals => {:f => f} %>
37   -<% end %>
38   -
39   -<% unless @terms_of_use.blank? %>
40   - <div id='terms-of-use-box' class='formfieldline'>
41   - <%= _("By clicking on 'I accept the terms of use' below you are agreeing to the %s") %
42   - link_to_function(_('Terms of use'), nil) do |page|
43   - page['terms-of-use'].show
44   - end %>
45   -
46   - <div id='terms-of-use' style='display: none;'>
47   - <%= @terms_of_use %>
48   - <%= link_to_function(_('Hide'), nil) do |page|
49   - page['terms-of-use'].hide
50   - end %>
  64 +<div id="signup-form-profile">
  65 +
  66 + <% labelled_fields_for :profile_data, @person do |f| %>
  67 + <%= render :partial => 'profile_editor/person_form', :locals => {:f => f} %>
  68 + <% end %>
  69 +
  70 + <% unless @terms_of_use.blank? %>
  71 + <div id='terms-of-use-box' class='formfieldline'>
  72 + <%= labelled_check_box(_('I accept the %s') % link_to(_('terms of use'), {:controller => 'home', :action => 'terms'}, :target => '_blank'), 'user[terms_accepted]') %>
51 73 </div>
52   - <p><%= labelled_check_box(environment.terms_of_use_acceptance_text.blank? ? _('I accept the terms of use') : environment.terms_of_use_acceptance_text, 'user[terms_accepted]') %></p>
53   - </div>
54   -<% end %>
55   -
56   -<% if params[:enterprise_code] %>
57   - <%= hidden_field_tag :enterprise_code, params[:enterprise_code] %>
58   - <%= hidden_field_tag :answer, params[:answer] %>
59   - <%= hidden_field_tag :terms_accepted, params[:terms_accepted] %>
60   - <%= hidden_field_tag :new_user, true %>
61   -<% end %>
62   -
63   -<% button_bar do %>
64   - <%= submit_button('save', _('Sign up'), :cancel => {:action => 'index'}, :class => 'icon-menu-login') %>
65   -<% end %>
  74 + <% end %>
  75 +
  76 + <% if params[:enterprise_code] %>
  77 + <%= hidden_field_tag :enterprise_code, params[:enterprise_code] %>
  78 + <%= hidden_field_tag :answer, params[:answer] %>
  79 + <%= hidden_field_tag :terms_accepted, params[:terms_accepted] %>
  80 + <%= hidden_field_tag :new_user, true %>
  81 + <% end %>
  82 +</div>
  83 +
  84 +<p style="text-align: center">
  85 + <%= submit_button('save', _('Create my account')) %>
  86 +</p>
  87 +
66 88 <% end -%>
  89 +
  90 +<script type="text/javascript">
  91 +jQuery(function($) {
  92 + $('#signup-form input[type=text], #signup-form textarea').each(function() {
  93 + if ($(this).attr('rel')) var default_value = $(this).attr('rel').toLowerCase();
  94 + if ($(this).val() == '') $(this).val(default_value);
  95 + $(this).bind('focus', function() {
  96 + if ($(this).val() == default_value) $(this).val('');
  97 + });
  98 + $(this).bind('blur', function() {
  99 + if ($(this).val() == '') {
  100 + $(this).val(default_value);
  101 + $(this).removeClass('filled-in');
  102 + }
  103 + else $(this).addClass('filled-in');
  104 + });
  105 + });
  106 +
  107 + $('#signup-form').bind('submit', function() {
  108 + $('#signup-form input[type=text], #signup-form textarea').each(function() {
  109 + if ($(this).attr('rel')) var default_value = $(this).attr('rel').toLowerCase();
  110 + if ($(this).val() == default_value) $(this).val('');
  111 + });
  112 + return true;
  113 + });
  114 +
  115 + $('#user_password_clear, #user_password_confirmation_clear').show();
  116 + $('#user_password_clear, #user_password_confirmation_clear').unbind();
  117 + $('#user_pw, #user_password_confirmation').hide();
  118 + $('#user_password_clear').focus(function() {
  119 + $(this).hide();
  120 + $('#user_pw').show();
  121 + $('#user_pw').focus();
  122 + });
  123 + $('#user_pw').focus(function() {
  124 + $('#password-balloon').fadeIn('slow');
  125 + });
  126 + $('#user_pw').blur(function() {
  127 + if ($(this).val() == '') {
  128 + $('#user_password_clear').show();
  129 + $(this).hide();
  130 + }
  131 + });
  132 + $('#user_password_confirmation_clear').focus(function() {
  133 + $(this).hide();
  134 + $('#user_password_confirmation').show();
  135 + $('#user_password_confirmation').focus();
  136 + });
  137 + $('#user_password_confirmation, #user_pw').blur(function() {
  138 + if ($('#user_password_confirmation').val() == '') {
  139 + $('#user_password_confirmation_clear').show();
  140 + $('#user_password_confirmation').hide();
  141 + } else if ($('#user_password_confirmation').val() == $('#user_pw').val()) {
  142 + $('#user_password_confirmation').addClass('passwords_match').removeClass('passwords_differ');
  143 + $('#user_pw').removeClass('invalid_input').addClass('valid_input');
  144 + $('#password-check').html("<p>&nbsp;</p>");
  145 + } else if ($('#user_password_confirmation').val() != $('#user_pw').val()) {
  146 + $('#user_password_confirmation').removeClass('passwords_match').addClass('passwords_differ');
  147 + $('#user_pw').addClass('invalid_input').removeClass('valid_input');
  148 + $('#password-check').html("<p><span class='unavailable'><%= _('Passwords don\'t match') %></span></p>");
  149 + }
  150 + $('#password-balloon').fadeOut('slow');
  151 + });
  152 + $('#user_login').focus(function() {
  153 + $('#signup-balloon').fadeIn('slow');
  154 + });
  155 + $('#user_login').blur(function() { $('#signup-balloon').fadeOut('slow'); });
  156 + $('#signup-form').validate({ rules: { 'user[email]': { email: true } }, messages: { 'user[email]' : '' } });
  157 +});
  158 +</script>
... ...