Commit 6daf9ba27c9135578f8156e49dfa62f574702d89

Authored by Victor Costa
2 parents bb996411 c5265b67

Merge branch 'master' into rails3-custom_fields

Conflicts:
	app/helpers/application_helper.rb
	app/views/profile/_person_profile.html.erb
Showing 1380 changed files with 86898 additions and 157983 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 1380 files displayed.

1 --ignore-dir=log 1 --ignore-dir=log
2 --ignore-dir=tmp 2 --ignore-dir=tmp
3 --ignore-dir=pkg 3 --ignore-dir=pkg
  4 +--ignore-dir=public/javascripts/cache
  5 +--ignore-dir=public/stylesheets/cache
@@ -40,7 +40,9 @@ Alessandro Palmeira + João M. M. Silva <alessandro.palmeira@gmail.com> @@ -40,7 +40,9 @@ Alessandro Palmeira + João M. M. Silva <alessandro.palmeira@gmail.com>
40 Alessandro Palmeira + Paulo Meirelles <alessandro.palmeira@gmail.com> 40 Alessandro Palmeira + Paulo Meirelles <alessandro.palmeira@gmail.com>
41 Alessandro Palmeira + Paulo Meirelles + João M. M. da Silva <alessandro.palmeira@gmail.com> 41 Alessandro Palmeira + Paulo Meirelles + João M. M. da Silva <alessandro.palmeira@gmail.com>
42 Alessandro Palmeira + Rafael Manzo <alessandro.palmeira@gmail.com> 42 Alessandro Palmeira + Rafael Manzo <alessandro.palmeira@gmail.com>
  43 +analosnak <analosnak@gmail.com>
43 Ana Losnak <analosnak@gmail.com> 44 Ana Losnak <analosnak@gmail.com>
  45 +Andre Bernardes <andrebsguedes@gmail.com>
44 Antonio Terceiro + Carlos Morais <terceiro@colivre.coop.br> 46 Antonio Terceiro + Carlos Morais <terceiro@colivre.coop.br>
45 Antonio Terceiro + Paulo Meirelles <terceiro@colivre.coop.br> 47 Antonio Terceiro + Paulo Meirelles <terceiro@colivre.coop.br>
46 Antonio Terceiro <terceiro@colivre.coop.br> 48 Antonio Terceiro <terceiro@colivre.coop.br>
@@ -80,7 +82,6 @@ Carlos Morais + Diego Araújo &lt;diegoamc90@gmail.com&gt; @@ -80,7 +82,6 @@ Carlos Morais + Diego Araújo &lt;diegoamc90@gmail.com&gt;
80 Carlos Morais + Eduardo Morais <carlos88morais@gmail.com> 82 Carlos Morais + Eduardo Morais <carlos88morais@gmail.com>
81 Carlos Morais + Paulo Meirelles <carlos88morais@gmail.com> 83 Carlos Morais + Paulo Meirelles <carlos88morais@gmail.com>
82 Carlos Morais + Pedro Leal <carlos88morais@gmail.com> 84 Carlos Morais + Pedro Leal <carlos88morais@gmail.com>
83 -Daniela Feitosa <dani@dohko.(none)>  
84 Daniel Alves + Diego Araújo <danpaulalves@gmail.com> 85 Daniel Alves + Diego Araújo <danpaulalves@gmail.com>
85 Daniel Alves + Diego Araújo <diegoamc90@gmail.com> 86 Daniel Alves + Diego Araújo <diegoamc90@gmail.com>
86 Daniel Alves + Diego Araújo + Guilherme Rojas <danpaulalves@gmail.com> 87 Daniel Alves + Diego Araújo + Guilherme Rojas <danpaulalves@gmail.com>
@@ -118,7 +119,6 @@ Diego Araújo + Renan Teruo &lt;diegoamc90@gmail.com&gt; @@ -118,7 +119,6 @@ Diego Araújo + Renan Teruo &lt;diegoamc90@gmail.com&gt;
118 Diego Araujo + Rodrigo Souto + Rafael Manzo <rr.manzo@gmail.com> 119 Diego Araujo + Rodrigo Souto + Rafael Manzo <rr.manzo@gmail.com>
119 Diego + Jefferson <diegoamc90@gmail.com> 120 Diego + Jefferson <diegoamc90@gmail.com>
120 Diego Martinez <diegoamc90@gmail.com> 121 Diego Martinez <diegoamc90@gmail.com>
121 -Diego Martinez <diego@diego-K55A.(none)>  
122 Diego + Renan <renanteruoc@gmail.com> 122 Diego + Renan <renanteruoc@gmail.com>
123 Eduardo Tourinho Edington <eduardo.edington@serpro.gov.br> 123 Eduardo Tourinho Edington <eduardo.edington@serpro.gov.br>
124 Evandro Jr <evandrojr@gmail.com> 124 Evandro Jr <evandrojr@gmail.com>
@@ -132,6 +132,7 @@ Francisco Marcelo de Araújo Lima Júnior &lt;maljunior@gmail.com&gt; @@ -132,6 +132,7 @@ Francisco Marcelo de Araújo Lima Júnior &lt;maljunior@gmail.com&gt;
132 Gabriela Navarro <navarro1703@gmail.com> 132 Gabriela Navarro <navarro1703@gmail.com>
133 Grazieno Pellegrino <grazieno@gmail.com> 133 Grazieno Pellegrino <grazieno@gmail.com>
134 Gust <darksshades@hotmail.com> 134 Gust <darksshades@hotmail.com>
  135 +Hebert Douglas <hebertdougl@gmail.com>
135 Hugo Melo <hugo@riseup.net> 136 Hugo Melo <hugo@riseup.net>
136 Isaac Canan <isaac@intelletto.com.br> 137 Isaac Canan <isaac@intelletto.com.br>
137 Italo Valcy <italo@dcc.ufba.br> 138 Italo Valcy <italo@dcc.ufba.br>
@@ -193,9 +194,11 @@ Luis David Aguilar Carlos &lt;ludwig9003@gmail.com&gt; @@ -193,9 +194,11 @@ Luis David Aguilar Carlos &lt;ludwig9003@gmail.com&gt;
193 Luiz Fernando de Freitas Matos <luiz@luizff.matos@gmail.com> 194 Luiz Fernando de Freitas Matos <luiz@luizff.matos@gmail.com>
194 Marcos Ramos <ms.ramos@outlook.com> 195 Marcos Ramos <ms.ramos@outlook.com>
195 Martín Olivera <molivera@solar.org.ar> 196 Martín Olivera <molivera@solar.org.ar>
  197 +Michal Čihař <michal@cihar.com>
196 Moises Machado <moises@colivre.coop.br> 198 Moises Machado <moises@colivre.coop.br>
197 Naíla Alves <naila@colivre.coop.br> 199 Naíla Alves <naila@colivre.coop.br>
198 Nanda Lopes <nanda.listas+psl@gmail.com> 200 Nanda Lopes <nanda.listas+psl@gmail.com>
  201 +Parley Martins <parleypachecomartins@gmail.com>
199 Paulo Meirelles + Alessandro Palmeira + João M. M. da Silva <paulo@softwarelivre.org> 202 Paulo Meirelles + Alessandro Palmeira + João M. M. da Silva <paulo@softwarelivre.org>
200 Paulo Meirelles + Alessandro Palmeira <paulo@softwarelivre.org> 203 Paulo Meirelles + Alessandro Palmeira <paulo@softwarelivre.org>
201 Paulo Meirelles + Carlos Morais <paulo@softwarelivre.org> 204 Paulo Meirelles + Carlos Morais <paulo@softwarelivre.org>
@@ -218,6 +221,7 @@ Rafael Reggiani Manzo + João M. M. da Silva &lt;rr.manzo@gmail.com&gt; @@ -218,6 +221,7 @@ Rafael Reggiani Manzo + João M. M. da Silva &lt;rr.manzo@gmail.com&gt;
218 Rafael Reggiani Manzo <rr.manzo@gmail.com> 221 Rafael Reggiani Manzo <rr.manzo@gmail.com>
219 Raphaël Rousseau <raph@r4f.org> 222 Raphaël Rousseau <raph@r4f.org>
220 Raquel Lira <raquel.lira@gmail.com> 223 Raquel Lira <raquel.lira@gmail.com>
  224 +Raquel <rcordioli@gmail.com>
221 Renan Teruo + Caio Salgado <renanteruoc@gmail.com> 225 Renan Teruo + Caio Salgado <renanteruoc@gmail.com>
222 Renan Teruoc + Diego Araujo <renanteruoc@gmail.com> 226 Renan Teruoc + Diego Araujo <renanteruoc@gmail.com>
223 Renan Teruo + Diego Araujo <renanteruoc@gmail.com> 227 Renan Teruo + Diego Araujo <renanteruoc@gmail.com>
@@ -225,11 +229,13 @@ Renan Teruo + Diego Araújo &lt;renanteruoc@gmail.com&gt; @@ -225,11 +229,13 @@ Renan Teruo + Diego Araújo &lt;renanteruoc@gmail.com&gt;
225 Renan Teruo + Paulo Meirelles <renanteruoc@gmail.com> 229 Renan Teruo + Paulo Meirelles <renanteruoc@gmail.com>
226 Renan Teruo + Rafael Manzo <renanteruoc@gmail.com> 230 Renan Teruo + Rafael Manzo <renanteruoc@gmail.com>
227 Rodrigo Souto + Ana Losnak + Daniel Bucher + Caio Almeida + Leandro Nunes + Daniela Feitosa + Mariel Zasso <noosfero-br@listas.softwarelivre.org> 231 Rodrigo Souto + Ana Losnak + Daniel Bucher + Caio Almeida + Leandro Nunes + Daniela Feitosa + Mariel Zasso <noosfero-br@listas.softwarelivre.org>
228 -Rodrigo Souto <diguliu@gmail.com>  
229 Rodrigo Souto <rodrigo@colivre.coop.br> 232 Rodrigo Souto <rodrigo@colivre.coop.br>
230 Ronny Kursawe <kursawe.ronny@googlemail.com> 233 Ronny Kursawe <kursawe.ronny@googlemail.com>
231 root <root@debian.sdr.serpro> 234 root <root@debian.sdr.serpro>
232 Samuel R. C. Vale <srcvale@holoscopio.com> 235 Samuel R. C. Vale <srcvale@holoscopio.com>
  236 +Tallys Martins <tallysmartins@gmail.com>
  237 +tallys <tallys@tallys.(none)>
  238 +Thiago Zoroastro <thiago.zoroastro@bol.com.br>
233 Valessio Brito <contato@valessiobrito.com.br> 239 Valessio Brito <contato@valessiobrito.com.br>
234 Valessio Brito <contato@valessiobrito.info> 240 Valessio Brito <contato@valessiobrito.info>
235 Valessio Brito <valessio@gmail.com> 241 Valessio Brito <valessio@gmail.com>
DEVELOPMENT.md 0 → 100644
@@ -0,0 +1,124 @@ @@ -0,0 +1,124 @@
  1 +# Noosfero Development Policy
  2 +
  3 +## Developer Roles
  4 +
  5 +* *Developers* are everyone that is contributing code to Noosfero.
  6 +* *Committers* are the people with direct commit access to the Noosfero source
  7 + code. They are responsible for reviewing contributions from other developers
  8 + and integrating them in the Noosfero code base. They are the members of the
  9 + [Noosfero group on Gitlab](https://gitlab.com/groups/noosfero/members).
  10 +* *Release managers* are the people that are managing the release of a new
  11 + Noosfero version and/or the maintainance work of an existing Noosfero stable
  12 + branch. See MAINTAINANCE.md for details on the maintaince policy.
  13 +
  14 +## Development process
  15 +
  16 +* Every new feature or non-trivial bugfix should be reviewed by at least one
  17 + committer. This must be the case even if the original author is a committer.
  18 +
  19 + * In the case the original author is a committer, he/she should feel free to
  20 + commit directly if after 1 week nobody has provided any kind of feedback.
  21 +
  22 + * Developers who are not committers should feel free to ping committers if
  23 + they do not get feedback on their contributions after 1 week.
  24 +
  25 + * On GitLab, one can just add a comment to the merge request; one can also
  26 + @-mention specific committers or other developers who have expertise on
  27 + the area of the contribution.
  28 +
  29 + * Committers should follow the activity of the project, and try to help
  30 + reviewing contributions from others as much as possible.
  31 +
  32 + * On GitLab one can get emails for all activity on a project by setting the
  33 + [notification settings](https://gitlab.com/profile/notifications) to
  34 + "watch".
  35 +
  36 + * Anyone can help by reviewing contributions. Committers are the only ones
  37 + who can give the final approval to a contribution, but everyone is welcome
  38 + to help with code review, testing, etc.
  39 +
  40 + * See note above about setting up notification on GitLab.
  41 +
  42 +* Committers should feel free to push trivial (or urgent) changes directly.
  43 + There are no strict rule on what makes a change trivial or urgent; committers
  44 + are expected to exercise good judgement on a case by case basis.
  45 +
  46 + * Usually changes to the database are not trivial.
  47 +
  48 +* In the case of unsolvable conflict between commiters regarding any change to
  49 + the code, the current release manager(s) will have the final say in the
  50 + matter.
  51 +
  52 +* Release managers are responsible for stablishing a release schedule, and
  53 + about deciding when and what to release.
  54 +
  55 + * Release managers should announce release schedules to the project mailing
  56 + lists in advance.
  57 +
  58 + * The release schedule may include a period of feature freeze, during which
  59 + no new features or any other changes that are not pre-approved by the
  60 + release manager must be committed to the repository.
  61 +
  62 + * Committers must respect the release schedule and feature freezes.
  63 +
  64 +## Maintainance process
  65 +
  66 +### Not all feature releases will be maintained as a stable release
  67 +
  68 +We will be choosing specific release series to be maintained as stable
  69 +releases.
  70 +
  71 +This means that a given release is not guaranteed to be maintained as a stable
  72 +release, but does *not* mean it won't be. Any committer (or anyone, really) can
  73 +decide to maintain a given release as stable and seek help from others to do
  74 +so.
  75 +
  76 +### No merges from stable branches to master
  77 +
  78 +*All* changes must be submitted against the master branch first, and when
  79 +applicable, backported to the desired stable releases. Exceptions to this rules
  80 +are bug fixes that only apply to a given stable branch and not to master.
  81 +
  82 +In the past we had non-trivial changes accepted into stable releases while
  83 +master was way ahead (e.g. during the rails3 migration period), that made the
  84 +merge back into master very painful. By eliminating the need to do these
  85 +merges, we save time for the people responsible for the release, and eliminate
  86 +the possibility of human errors or oversights causing changes to be accepted
  87 +into stable that will be a problem to merge back into master.
  88 +
  89 +By getting all fixes in master first, we improve the chances that a future
  90 +release will not present regressions against bugs that should already be fixed,
  91 +but the fixes got lost in a big, complicated merge (and those won't exist
  92 +anymore, at least not from stable branches to master).
  93 +
  94 +After a fix gets into master, backporting changes into a stable release branch
  95 +is the responsibility of whoever is maintaing that branch, and those interested
  96 +in it. The stable branch release manager(s) are entitled the final say on any
  97 +matters related to that branch.
  98 +
  99 +## Apendix A: how to become a committer
  100 +
  101 +Every developer that wants to be a committer should create [an issue on
  102 +Gitlab](https://gitlab.com/noosfero/noosfero/issues) requesting to be added as
  103 +a committer. This request must include information about the requestor's
  104 +previous contributions to the project.
  105 +
  106 +If 2 or more commiters consider second the request, the requestor is accepted
  107 +as new commiter and added to the Noosfero group.
  108 +
  109 +The existing committers are free to choose whatever criteria they want to
  110 +second the request, but they must be sure that the new committer is a
  111 +responsible developer and knows what she/he is doing. They must be aware that
  112 +seconding these requests means seconding the actions of the new committer: if
  113 +the new committer screw up, her/his seconds screwed up.
  114 +
  115 +## Apendix B: how to become a release manager
  116 +
  117 +A new release manager for the development version of Noosfero (i.e. the one
  118 +that includes new features, a.k.a. the master branch) is apointed by the
  119 +current release manager, and must be a committer first.
  120 +
  121 +Release managers for stable branches are self-appointed, i.e. whoever takes the
  122 +work takes the role. In case of a conflict (e.g. 2+ different people want to do
  123 +the work but can't agree on working together), the development release manager
  124 +decides.
1 source "https://rubygems.org" 1 source "https://rubygems.org"
2 -gem 'rails'  
3 -gem 'fast_gettext'  
4 -gem 'acts-as-taggable-on'  
5 -gem 'prototype-rails'  
6 -gem 'prototype_legacy_helper', '0.0.0', :path => 'vendor/prototype_legacy_helper'  
7 -gem 'rails_autolink'  
8 -gem 'pg'  
9 -gem 'rmagick'  
10 -gem 'RedCloth'  
11 -gem 'will_paginate'  
12 -gem 'ruby-feedparser'  
13 -gem 'daemons'  
14 -gem 'thin'  
15 -gem 'hpricot'  
16 -gem 'nokogiri' 2 +gem 'rails', '~> 3.2.19'
  3 +gem 'fast_gettext', '~> 0.6.8'
  4 +gem 'acts-as-taggable-on', '~> 3.0.2'
  5 +gem 'prototype-rails', '~> 3.2.1'
  6 +gem 'prototype_legacy_helper', '0.0.0', :path => 'vendor/prototype_legacy_helper'
  7 +gem 'rails_autolink', '~> 1.1.5'
  8 +gem 'pg', '~> 0.13.2'
  9 +gem 'rmagick', '~> 2.13.1'
  10 +gem 'RedCloth', '~> 4.2.9'
  11 +gem 'will_paginate', '~> 3.0.3'
  12 +gem 'ruby-feedparser', '~> 0.7'
  13 +gem 'daemons', '~> 1.1.5'
  14 +gem 'thin', '~> 1.3.1'
  15 +gem 'hpricot', '~> 0.8.6'
  16 +gem 'nokogiri', '~> 1.5.5'
17 gem 'rake', :require => false 17 gem 'rake', :require => false
18 -gem 'rest-client'  
19 -gem 'exception_notification' 18 +gem 'rest-client', '~> 1.6.7'
  19 +gem 'exception_notification', '~> 4.0.1'
  20 +gem 'gettext', '~> 2.2.1', :require => false, :group => :development
  21 +gem 'locale', '~> 2.0.5'
20 22
21 # FIXME list here all actual dependencies (i.e. the ones in debian/control), 23 # FIXME list here all actual dependencies (i.e. the ones in debian/control),
22 # with their GEM names (not the Debian package names) 24 # with their GEM names (not the Debian package names)
23 25
24 group :production do 26 group :production do
25 - gem 'dalli' 27 + gem 'dalli', '~> 2.7.0'
26 end 28 end
27 29
28 group :test do 30 group :test do
29 - gem 'rspec'  
30 - gem 'rspec-rails'  
31 - gem 'mocha', :require => false 31 + gem 'rspec', '~> 2.10.0'
  32 + gem 'rspec-rails', '~> 2.10.1'
  33 + gem 'mocha', '~> 1.1.0', :require => false
32 end 34 end
33 35
34 group :cucumber do 36 group :cucumber do
35 - gem 'cucumber-rails', :require => false  
36 - gem 'capybara'  
37 - gem 'cucumber'  
38 - gem 'database_cleaner'  
39 - gem 'selenium-webdriver' 37 + gem 'cucumber-rails', '~> 1.0.6', :require => false
  38 + gem 'capybara', '~> 2.1.0'
  39 + gem 'cucumber', '~> 1.0.6'
  40 + gem 'database_cleaner', '~> 1.2.0'
  41 + gem 'selenium-webdriver', '~> 2.39.0'
40 end 42 end
41 43
42 -# include plugin gemfiles  
43 -Dir.glob(File.join('config', 'plugins', '*')).each do |plugin|  
44 - plugin_gemfile = File.join(plugin, 'Gemfile')  
45 - eval File.read(plugin_gemfile) if File.exists?(plugin_gemfile) 44 +# include gemfiles from enabled plugins
  45 +# plugins in baseplugins/ are not included on purpose. They should not have any
  46 +# dependencies.
  47 +Dir.glob('config/plugins/*/Gemfile').each do |gemfile|
  48 + eval File.read(gemfile)
46 end 49 end
Gemfile.lock
@@ -1,191 +0,0 @@ @@ -1,191 +0,0 @@
1 -PATH  
2 - remote: vendor/prototype_legacy_helper  
3 - specs:  
4 - prototype_legacy_helper (0.0.0)  
5 -  
6 -GEM  
7 - remote: https://rubygems.org/  
8 - specs:  
9 - RedCloth (4.2.9)  
10 - actionmailer (3.2.6)  
11 - actionpack (= 3.2.6)  
12 - mail (~> 2.4.4)  
13 - actionpack (3.2.6)  
14 - activemodel (= 3.2.6)  
15 - activesupport (= 3.2.6)  
16 - builder (~> 3.0.0)  
17 - erubis (~> 2.7.0)  
18 - journey (~> 1.0.1)  
19 - rack (~> 1.4.0)  
20 - rack-cache (~> 1.2)  
21 - rack-test (~> 0.6.1)  
22 - sprockets (~> 2.1.3)  
23 - activemodel (3.2.6)  
24 - activesupport (= 3.2.6)  
25 - builder (~> 3.0.0)  
26 - activerecord (3.2.6)  
27 - activemodel (= 3.2.6)  
28 - activesupport (= 3.2.6)  
29 - arel (~> 3.0.2)  
30 - tzinfo (~> 0.3.29)  
31 - activeresource (3.2.6)  
32 - activemodel (= 3.2.6)  
33 - activesupport (= 3.2.6)  
34 - activesupport (3.2.6)  
35 - i18n (~> 0.6)  
36 - multi_json (~> 1.0)  
37 - acts-as-taggable-on (3.0.2)  
38 - rails (>= 3, < 5)  
39 - arel (3.0.2)  
40 - builder (3.0.0)  
41 - capybara (2.1.0)  
42 - mime-types (>= 1.16)  
43 - nokogiri (>= 1.3.3)  
44 - rack (>= 1.0.0)  
45 - rack-test (>= 0.5.4)  
46 - xpath (~> 2.0)  
47 - childprocess (0.3.3)  
48 - ffi (~> 1.0.6)  
49 - cucumber (1.0.6)  
50 - builder (>= 2.1.2)  
51 - diff-lcs (>= 1.1.2)  
52 - gherkin (~> 2.4.18)  
53 - json (>= 1.4.6)  
54 - term-ansicolor (>= 1.0.6)  
55 - cucumber-rails (1.0.6)  
56 - capybara (>= 1.1.1)  
57 - cucumber (>= 1.0.6)  
58 - nokogiri (>= 1.5.0)  
59 - daemons (1.1.5)  
60 - dalli (2.7.0)  
61 - database_cleaner (1.2.0)  
62 - diff-lcs (1.1.3)  
63 - erubis (2.7.0)  
64 - eventmachine (0.12.10)  
65 - exception_notification (4.0.1)  
66 - actionmailer (>= 3.0.4)  
67 - activesupport (>= 3.0.4)  
68 - fast_gettext (0.6.8)  
69 - ffi (1.0.11)  
70 - gherkin (2.4.21)  
71 - json (>= 1.4.6)  
72 - hike (1.2.1)  
73 - hpricot (0.8.6)  
74 - i18n (0.6.0)  
75 - journey (1.0.3)  
76 - json (1.7.3)  
77 - mail (2.4.4)  
78 - i18n (>= 0.4.0)  
79 - mime-types (~> 1.16)  
80 - treetop (~> 1.4.8)  
81 - metaclass (0.0.1)  
82 - mime-types (1.19)  
83 - mocha (0.11.3)  
84 - metaclass (~> 0.0.1)  
85 - multi_json (1.3.6)  
86 - nokogiri (1.5.5)  
87 - pg (0.13.2)  
88 - polyglot (0.3.3)  
89 - prototype-rails (3.2.1)  
90 - rails (~> 3.2)  
91 - rack (1.4.1)  
92 - rack-cache (1.2)  
93 - rack (>= 0.4)  
94 - rack-ssl (1.3.2)  
95 - rack  
96 - rack-test (0.6.1)  
97 - rack (>= 1.0)  
98 - rails (3.2.6)  
99 - actionmailer (= 3.2.6)  
100 - actionpack (= 3.2.6)  
101 - activerecord (= 3.2.6)  
102 - activeresource (= 3.2.6)  
103 - activesupport (= 3.2.6)  
104 - bundler (~> 1.0)  
105 - railties (= 3.2.6)  
106 - rails_autolink (1.1.5)  
107 - rails (> 3.1)  
108 - railties (3.2.6)  
109 - actionpack (= 3.2.6)  
110 - activesupport (= 3.2.6)  
111 - rack-ssl (~> 1.3.2)  
112 - rake (>= 0.8.7)  
113 - rdoc (~> 3.4)  
114 - thor (>= 0.14.6, < 2.0)  
115 - rake (0.9.2.2)  
116 - rdoc (3.9.4)  
117 - rest-client (1.6.7)  
118 - mime-types (>= 1.16)  
119 - rmagick (2.13.1)  
120 - rspec (2.10.0)  
121 - rspec-core (~> 2.10.0)  
122 - rspec-expectations (~> 2.10.0)  
123 - rspec-mocks (~> 2.10.0)  
124 - rspec-core (2.10.1)  
125 - rspec-expectations (2.10.0)  
126 - diff-lcs (~> 1.1.3)  
127 - rspec-mocks (2.10.1)  
128 - rspec-rails (2.10.1)  
129 - actionpack (>= 3.0)  
130 - activesupport (>= 3.0)  
131 - railties (>= 3.0)  
132 - rspec (~> 2.10.0)  
133 - ruby-feedparser (0.7)  
134 - rubyzip (1.1.2)  
135 - selenium-webdriver (2.39.0)  
136 - childprocess (>= 0.2.5)  
137 - multi_json (~> 1.0)  
138 - rubyzip (~> 1.0)  
139 - websocket (~> 1.0.4)  
140 - sprockets (2.1.3)  
141 - hike (~> 1.2)  
142 - multi_json (~> 1.0)  
143 - rack (~> 1.0)  
144 - tilt (~> 1.1, != 1.3.0)  
145 - term-ansicolor (1.0.7)  
146 - thin (1.3.1)  
147 - daemons (>= 1.0.9)  
148 - eventmachine (>= 0.12.6)  
149 - rack (>= 1.0.0)  
150 - thor (0.15.3)  
151 - tilt (1.3.3)  
152 - treetop (1.4.10)  
153 - polyglot  
154 - polyglot (>= 0.3.1)  
155 - tzinfo (0.3.33)  
156 - websocket (1.0.7)  
157 - will_paginate (3.0.3)  
158 - xpath (2.0.0)  
159 - nokogiri (~> 1.3)  
160 -  
161 -PLATFORMS  
162 - ruby  
163 -  
164 -DEPENDENCIES  
165 - RedCloth  
166 - acts-as-taggable-on  
167 - capybara  
168 - cucumber  
169 - cucumber-rails  
170 - daemons  
171 - dalli  
172 - database_cleaner  
173 - exception_notification  
174 - fast_gettext  
175 - hpricot  
176 - mocha  
177 - nokogiri  
178 - pg  
179 - prototype-rails  
180 - prototype_legacy_helper (= 0.0.0)!  
181 - rails  
182 - rails_autolink  
183 - rake  
184 - rest-client  
185 - rmagick  
186 - rspec  
187 - rspec-rails  
188 - ruby-feedparser  
189 - selenium-webdriver  
190 - thin  
191 - will_paginate  
INSTALL.https.md
1 -Setup Noosfero to use HTTPS  
2 -=========================== 1 +# Setup Noosfero to use HTTPS
3 2
4 This document assumes that you have a fully and clean Noosfero 3 This document assumes that you have a fully and clean Noosfero
5 installation as explained at the `INSTALL.md` file. 4 installation as explained at the `INSTALL.md` file.
6 5
7 -SSL certificate  
8 -+++++++++++++++ 6 +## Creating a self-signed SSL certificate
9 7
10 You should get a valid SSL certificate, but if you want to test 8 You should get a valid SSL certificate, but if you want to test
11 your setup before, you could generate a self-signed certificate 9 your setup before, you could generate a self-signed certificate
@@ -17,99 +15,106 @@ as below: @@ -17,99 +15,106 @@ as below:
17 # openssl req -new -x509 -nodes -sha1 -days $[10*365] -key noosfero.key > noosfero.cert 15 # openssl req -new -x509 -nodes -sha1 -days $[10*365] -key noosfero.key > noosfero.cert
18 # cat noosfero.key noosfero.cert > noosfero.pem 16 # cat noosfero.key noosfero.cert > noosfero.pem
19 17
  18 +## Web server configuration
  19 +
20 There are two ways of using SSL with Noosfero: 1) If you are not using 20 There are two ways of using SSL with Noosfero: 1) If you are not using
21 Varnish; and 2) If you are using Varnish. 21 Varnish; and 2) If you are using Varnish.
22 22
23 -1) If you are are not using Varnish  
24 -+++++++++++++++++++++++++++++++++++ 23 +### 1) If you are are not using Varnish
25 24
26 Simply do a redirect in apache to force all connections with SSL: 25 Simply do a redirect in apache to force all connections with SSL:
27 26
28 - <VirtualHost *:8080>  
29 - ServerName test.stoa.usp.br  
30 -  
31 - Redirect / https://example.com/  
32 - </VirtualHost> 27 +```
  28 +<VirtualHost *:8080>
  29 + ServerName test.stoa.usp.br
  30 + Redirect / https://example.com/
  31 +</VirtualHost>
  32 +```
33 33
34 And set a vhost to receive then: 34 And set a vhost to receive then:
35 35
36 - <VirtualHost *:443>  
37 - ServerName example.com  
38 -  
39 - SSLEngine On  
40 - SSLCertificateFile /etc/ssl/certs/cert.pem  
41 - SSLCertificateKeyFile /etc/ssl/private/cert.key  
42 -  
43 - Include /etc/noosfero/apache/virtualhost.conf  
44 - </VirtualHost> 36 +```
  37 +<VirtualHost *:443>
  38 + ServerName example.com
  39 + SSLEngine On
  40 + SSLCertificateFile /etc/ssl/certs/cert.pem
  41 + SSLCertificateKeyFile /etc/ssl/private/cert.key
  42 + Include /etc/noosfero/apache/virtualhost.conf
  43 +</VirtualHost>
  44 +```
45 45
46 Be aware that if you had configured varnish, the requests won't reach 46 Be aware that if you had configured varnish, the requests won't reach
47 it with this configuration. 47 it with this configuration.
48 48
49 -2) If you are using Varnish  
50 -+++++++++++++++++++++++++++  
51 -  
52 -Varnish isn't able to communicate with the SSL protocol, so we will  
53 -need some one who do this and Pound[1] can do the job. In order to  
54 -install it in Debian based systems: 49 +### 2) If you are using Varnish
55 50
56 - $ sudo apt-get install pound 51 +Varnish isn't able to communicate with the SSL protocol, so we will need some
  52 +one else who do this and [Pound](http://www.apsis.ch/pound) can do the job. In
  53 +order to install it in Debian based systems:
57 54
58 -Set Varnish to listen in other port than 80: 55 +```
  56 +$ sudo apt-get install pound
  57 +```
59 58
60 -/etc/defaults/varnish  
61 ---------------------- 59 +Set Varnish to listen in other port than 80 in `/etc/defaults/varnish`:
62 60
63 - DAEMON_OPTS="-a localhost:6081 \  
64 - -T localhost:6082 \  
65 - -f /etc/varnish/default.vcl \  
66 - -S /etc/varnish/secret \  
67 - -s file,/var/lib/varnish/$INSTANCE/varnish_storage.bin,1G" 61 +```
  62 +DAEMON_OPTS="-a localhost:6081 \
  63 + -T localhost:6082 \
  64 + -f /etc/varnish/default.vcl \
  65 + -S /etc/varnish/secret \
  66 + -s file,/var/lib/varnish/$INSTANCE/varnish_storage.bin,1G"
  67 +```
68 68
69 Configure Pound: 69 Configure Pound:
70 70
71 - # cp /usr/share/noosfero/etc/pound.cfg /etc/pound/  
72 -  
73 -Edit /etc/pound.cfg and set the IP and domain of your server. 71 +```
  72 +# cp /usr/share/noosfero/etc/pound.cfg /etc/pound/
  73 +```
74 74
75 -Configure Pound to start at system initialization: 75 +Edit `/etc/pound.cfg` and set the IP and domain of your server.
76 76
77 -/etc/default/pound 77 +Configure Pound to start at system initialization. At `/etc/default/pound`:
78 ------------------ 78 ------------------
79 79
80 - startup=1 80 +```
  81 +startup=1
  82 +```
81 83
82 -Set Apache to only listen to localhost: 84 +Set Apache to only listen to localhost, at `/etc/apache2/ports.conf`:
83 85
84 -/etc/apache2/ports.conf  
85 ------------------------  
86 -  
87 - Listen 127.0.0.1:8080 86 +```
  87 +Listen 127.0.0.1:8080
  88 +```
88 89
89 Restart the services: 90 Restart the services:
90 91
91 - $ sudo service apache2 restart  
92 - $ sudo service varnish restart 92 +```
  93 +$ sudo service apache2 restart
  94 +$ sudo service varnish restart
  95 +```
93 96
94 Start pound: 97 Start pound:
95 98
96 - $ sudo service pound start  
97 -  
98 -[1] http://www.apsis.ch/pound 99 +```
  100 +$ sudo service pound start
  101 +```
99 102
100 -Noosfero XMPP chat  
101 -++++++++++++++++++ 103 +## Noosfero XMPP chat
102 104
103 If you want to use chat over HTTPS, then you should add the domain 105 If you want to use chat over HTTPS, then you should add the domain
104 -and IP of your server in the /etc/hosts file, example: 106 +and IP of your server in the /etc/hosts file, example
105 107
106 -/etc/hosts  
107 ----------- 108 +`/etc/hosts:`
108 109
109 - 192.168.1.86 mydomain.example.com 110 +```
  111 +192.168.1.86 mydomain.example.com
  112 +```
110 113
111 -Also, it's recomended that you remove lines above from the file 114 +Also, it's recomended that you remove the lines below from the file
112 `/etc/apache2/sites-enabled/noosfero`: 115 `/etc/apache2/sites-enabled/noosfero`:
113 116
114 - RewriteEngine On  
115 - Include /usr/share/noosfero/util/chat/apache/xmpp.conf 117 +```
  118 +RewriteEngine On
  119 +Include /usr/share/noosfero/util/chat/apache/xmpp.conf
  120 +```
INSTALL.locales.md 0 → 100644
@@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
  1 +Using custom locales
  2 +====================
  3 +
  4 +Personalized translations go into the `config/custom_locales/` directory.
  5 +Custom locales can be identified by the rails environment, schema name in a
  6 +multitenancy setup or domain name until the first dot (e.g env1.coop.br for the
  7 +example below).
  8 +
  9 +Currently, the only filename prefix for the localization file which is
  10 +processed is "environment". For instance, a POT file would be called
  11 +"environment.pot".
  12 +
  13 +The structure of an environment named env1 with custom translations for both
  14 +Portuguese and Spanish and an environment named env2 with custom Russian
  15 +translation would be:
  16 +
  17 + config/
  18 + custom_locales/
  19 + env1/
  20 + environment.pot
  21 + pt/
  22 + environment.po
  23 + es/
  24 + environment.po
  25 + env2/
  26 + environment.pot
  27 + ru/
  28 + environment.po
  29 +
@@ -186,8 +186,8 @@ Apache instalation @@ -186,8 +186,8 @@ Apache instalation
186 186
187 # apt-get install apache2 187 # apt-get install apache2
188 188
189 -Apache configuration  
190 --------------------- 189 +Configuration - noosfero at /
  190 +-----------------------------
191 191
192 First you have to enable the following some apache modules: 192 First you have to enable the following some apache modules:
193 193
@@ -257,6 +257,62 @@ Now restart your apache server (as root): @@ -257,6 +257,62 @@ Now restart your apache server (as root):
257 257
258 # invoke-rc.d apache2 restart 258 # invoke-rc.d apache2 restart
259 259
  260 +Configuration - noosfero at a /subdirectory
  261 +-------------------------------------------
  262 +
  263 +This section describes how to configure noosfero at a subdirectory, what is
  264 +specially useful when you want Noosfero to share a domain name with other
  265 +applications. For example you can host noosfero at yourdomain.com/social, a
  266 +webmail application at yourdomain.com/webmail, and have a static HTML website
  267 +at yourdomain.com/.
  268 +
  269 +**NOTE:** Some plugins might not work well with this setting. Before deploying
  270 +this setting, make sure you test that everything you need works properly with
  271 +it.
  272 +
  273 +The configuration is similar to the main configuration instructions, except for
  274 +the following points. In the description below, replace '/subdirectory' with
  275 +the actual subdirectory you want.
  276 +
  277 +1) add a `prefix: /subdirectory` line to your thin configuration file (thin.yml).
  278 +
  279 +1.1) remember to restart the noosfero application server whenever you make
  280 +changes to that configuration file.
  281 +
  282 + # service noosfero restart
  283 +
  284 +2) add a line saying `export RAILS_RELATIVE_URL_ROOT=/subdirectory` to
  285 +/etc/default/noosfero (you can create it with just this line if it does not
  286 +exist already).
  287 +
  288 +3) You should add the following apache configuration to an existing virtual
  289 +host (plus the `<Proxy balancer://noosfero>` section as displayed above):
  290 +
  291 +```
  292 +Alias /subdirectory /path/to/noosfero/public
  293 +<Directory "/path/to/noosfero/public">
  294 + Options FollowSymLinks
  295 + AllowOverride None
  296 + Order Allow,Deny
  297 + Allow from all
  298 +
  299 + Include /path/to/noosfero/etc/noosfero/apache/cache.conf
  300 +
  301 + RewriteEngine On
  302 + RewriteBase /subdirectory
  303 + # Rewrite index to check for static index.html
  304 + RewriteRule ^$ index.html [QSA]
  305 + # Rewrite to check for Rails cached page
  306 + RewriteRule ^([^.]+)$ $1.html [QSA]
  307 + RewriteCond %{REQUEST_FILENAME} !-f
  308 + RewriteRule ^(.*)$ http://localhost:3000%{REQUEST_URI} [P,QSA,L]
  309 +</Directory>
  310 +```
  311 +
  312 +3.1) remember to reload the apache server whenever any apache configuration
  313 +file changes.
  314 +
  315 + # sudo service apache2 reload
260 316
261 Enabling exception notifications 317 Enabling exception notifications
262 ================================ 318 ================================
@@ -6,3 +6,13 @@ @@ -6,3 +6,13 @@
6 require File.expand_path('../config/application', __FILE__) 6 require File.expand_path('../config/application', __FILE__)
7 7
8 Noosfero::Application.load_tasks 8 Noosfero::Application.load_tasks
  9 +
  10 +[
  11 + "baseplugins/*/{tasks,lib/tasks,rails/tasks}/**/*.rake",
  12 + "config/plugins/*/{tasks,lib/tasks,rails/tasks}/**/*.rake",
  13 + "config/plugins/*/vendor/plugins/*/{tasks,lib/tasks,rails/tasks}/**/*.rake",
  14 +].map do |pattern|
  15 + Dir.glob(pattern).sort
  16 +end.flatten.each do |taskfile|
  17 + load taskfile
  18 +end
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 3
4 VAGRANTFILE_API_VERSION = "2" 4 VAGRANTFILE_API_VERSION = "2"
5 Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| 5 Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
6 - config.vm.box = "debian-wheezy" 6 + config.vm.box = ENV.fetch('VAGRANT_BOX', "debian-wheezy")
7 config.vm.network :forwarded_port, host: 3000, guest: 3000 7 config.vm.network :forwarded_port, host: 3000, guest: 3000
8 config.vm.provision :shell do |shell| 8 config.vm.provision :shell do |shell|
9 shell.inline = 'su vagrant -c /vagrant/script/vagrant' 9 shell.inline = 'su vagrant -c /vagrant/script/vagrant'
app/controllers/admin/admin_panel_controller.rb
@@ -71,4 +71,22 @@ class AdminPanelController &lt; AdminController @@ -71,4 +71,22 @@ class AdminPanelController &lt; AdminController
71 end 71 end
72 end 72 end
73 end 73 end
  74 +
  75 + def manage_organizations_status
  76 + scope = environment.organizations
  77 + @filter = params[:filter] || 'any'
  78 + @title = "Organization profiles"
  79 + @title = @title+" - "+@filter if @filter != 'any'
  80 +
  81 + if @filter == 'enabled'
  82 + scope = scope.visible
  83 + elsif @filter == 'disabled'
  84 + scope = scope.disabled
  85 + end
  86 +
  87 + scope = scope.order('name ASC')
  88 +
  89 + @q = params[:q]
  90 + @collection = find_by_contents(:organizations, scope, @q, {:per_page => 10, :page => params[:npage]})[:results]
  91 + end
74 end 92 end
app/controllers/admin/plugin_admin_controller.rb 0 → 100644
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +class PluginAdminController < AdminController
  2 +
  3 + protect 'edit_environment_features', :environment
  4 +
  5 +end
app/controllers/admin/templates_controller.rb
@@ -40,8 +40,67 @@ class TemplatesController &lt; AdminController @@ -40,8 +40,67 @@ class TemplatesController &lt; AdminController
40 end 40 end
41 end 41 end
42 42
  43 + def set_community_as_default
  44 + begin
  45 + community = environment.communities.find(params[:template_id])
  46 + rescue ActiveRecord::RecordNotFound
  47 + message = _('Community not found. The template could no be changed.')
  48 + community = nil
  49 + end
  50 +
  51 + message = _('%s defined as default') % community.name if set_as_default(community)
  52 + session[:notice] = message
  53 +
  54 + redirect_to :action => 'index'
  55 + end
  56 +
  57 + def set_person_as_default
  58 + begin
  59 + person = environment.people.find(params[:template_id])
  60 + rescue ActiveRecord::RecordNotFound
  61 + message = _('Person not found. The template could no be changed.')
  62 + person = nil
  63 + end
  64 +
  65 + message = _('%s defined as default') % person.name if set_as_default(person)
  66 + session[:notice] = message
  67 +
  68 + redirect_to :action => 'index'
  69 + end
  70 +
  71 + def set_enterprise_as_default
  72 + begin
  73 + enterprise = environment.enterprises.find(params[:template_id])
  74 + rescue ActiveRecord::RecordNotFound
  75 + message = _('Enterprise not found. The template could no be changed.')
  76 + enterprise = nil
  77 + end
  78 +
  79 + message = _('%s defined as default') % enterprise.name if set_as_default(enterprise)
  80 + session[:notice] = message
  81 +
  82 + redirect_to :action => 'index'
  83 + end
  84 +
43 private 85 private
44 86
  87 + def set_as_default(obj)
  88 + return nil if obj.nil?
  89 + case obj.class.name
  90 + when 'Community' then
  91 + environment.community_default_template = obj
  92 + environment.save!
  93 + when 'Person' then
  94 + environment.person_default_template = obj
  95 + environment.save!
  96 + when 'Enterprise' then
  97 + environment.enterprise_default_template = obj
  98 + environment.save!
  99 + else
  100 + nil
  101 + end
  102 + end
  103 +
45 def create_organization_template(klass) 104 def create_organization_template(klass)
46 identifier = params[:name].to_slug 105 identifier = params[:name].to_slug
47 template = klass.new(:name => params[:name], :identifier => identifier, :is_template => true) 106 template = klass.new(:name => params[:name], :identifier => identifier, :is_template => true)
app/controllers/application_controller.rb
@@ -40,7 +40,7 @@ class ApplicationController &lt; ActionController::Base @@ -40,7 +40,7 @@ class ApplicationController &lt; ActionController::Base
40 40
41 theme_layout = theme_option(:layout) 41 theme_layout = theme_option(:layout)
42 if theme_layout 42 if theme_layout
43 - theme_view_file('layouts/'+theme_layout) || theme_layout 43 + (theme_view_file('layouts/'+theme_layout) || theme_layout).to_s
44 else 44 else
45 'application' 45 'application'
46 end 46 end
@@ -127,6 +127,9 @@ class ApplicationController &lt; ActionController::Base @@ -127,6 +127,9 @@ class ApplicationController &lt; ActionController::Base
127 127
128 # TODO: move this logic somewhere else (Domain class?) 128 # TODO: move this logic somewhere else (Domain class?)
129 def detect_stuff_by_domain 129 def detect_stuff_by_domain
  130 + # Sets text domain based on request host for custom internationalization
  131 + FastGettext.text_domain = Domain.custom_locale(request.host)
  132 +
130 @domain = Domain.find_by_name(request.host) 133 @domain = Domain.find_by_name(request.host)
131 if @domain.nil? 134 if @domain.nil?
132 @environment = Environment.default 135 @environment = Environment.default
app/controllers/my_profile/cms_controller.rb
@@ -174,6 +174,8 @@ class CmsController &lt; MyProfileController @@ -174,6 +174,8 @@ class CmsController &lt; MyProfileController
174 174
175 post_only :set_home_page 175 post_only :set_home_page
176 def set_home_page 176 def set_home_page
  177 + return render_access_denied unless user.can_change_homepage?
  178 +
177 article = params[:id].nil? ? nil : profile.articles.find(params[:id]) 179 article = params[:id].nil? ? nil : profile.articles.find(params[:id])
178 profile.update_attribute(:home_page, article) 180 profile.update_attribute(:home_page, article)
179 181
@@ -212,6 +214,7 @@ class CmsController &lt; MyProfileController @@ -212,6 +214,7 @@ class CmsController &lt; MyProfileController
212 if @errors.any? 214 if @errors.any?
213 render :action => 'upload_files', :parent_id => @parent_id 215 render :action => 'upload_files', :parent_id => @parent_id
214 else 216 else
  217 + session[:notice] = _('File(s) successfully uploaded')
215 if @back_to 218 if @back_to
216 redirect_to @back_to 219 redirect_to @back_to
217 elsif @parent 220 elsif @parent
@@ -227,7 +230,7 @@ class CmsController &lt; MyProfileController @@ -227,7 +230,7 @@ class CmsController &lt; MyProfileController
227 @article = profile.articles.find(params[:id]) 230 @article = profile.articles.find(params[:id])
228 if request.post? 231 if request.post?
229 @article.destroy 232 @article.destroy
230 - session[:notice] = _("\"#{@article.name}\" was removed.") 233 + session[:notice] = _("\"%s\" was removed." % @article.name)
231 referer = Rails.application.routes.recognize_path URI.parse(request.referer).path rescue nil 234 referer = Rails.application.routes.recognize_path URI.parse(request.referer).path rescue nil
232 if referer and referer[:controller] == 'cms' and referer[:action] != 'edit' 235 if referer and referer[:controller] == 'cms' and referer[:action] != 'edit'
233 redirect_to referer 236 redirect_to referer
app/controllers/my_profile/friends_controller.rb 100644 → 100755
@@ -20,7 +20,7 @@ class FriendsController &lt; MyProfileController @@ -20,7 +20,7 @@ class FriendsController &lt; MyProfileController
20 20
21 class << self 21 class << self
22 def per_page 22 def per_page
23 - 10 23 + 12
24 end 24 end
25 end 25 end
26 def per_page 26 def per_page
app/controllers/my_profile/profile_design_controller.rb
@@ -3,7 +3,16 @@ class ProfileDesignController &lt; BoxOrganizerController @@ -3,7 +3,16 @@ class ProfileDesignController &lt; BoxOrganizerController
3 needs_profile 3 needs_profile
4 4
5 protect 'edit_profile_design', :profile 5 protect 'edit_profile_design', :profile
6 - 6 +
  7 + before_filter :protect_fixed_block, :only => [:save, :move_block]
  8 +
  9 + def protect_fixed_block
  10 + block = boxes_holder.blocks.find(params[:id].gsub(/^block-/, ''))
  11 + if block.fixed && !current_person.is_admin?
  12 + render_access_denied
  13 + end
  14 + end
  15 +
7 def available_blocks 16 def available_blocks
8 blocks = [ ArticleBlock, TagsBlock, RecentDocumentsBlock, ProfileInfoBlock, LinkListBlock, MyNetworkBlock, FeedReaderBlock, ProfileImageBlock, LocationBlock, SlideshowBlock, ProfileSearchBlock, HighlightsBlock ] 17 blocks = [ ArticleBlock, TagsBlock, RecentDocumentsBlock, ProfileInfoBlock, LinkListBlock, MyNetworkBlock, FeedReaderBlock, ProfileImageBlock, LocationBlock, SlideshowBlock, ProfileSearchBlock, HighlightsBlock ]
9 18
app/controllers/my_profile/profile_editor_controller.rb
@@ -19,14 +19,16 @@ class ProfileEditorController &lt; MyProfileController @@ -19,14 +19,16 @@ class ProfileEditorController &lt; MyProfileController
19 params[:profile_data][:custom_fields] ||= {} 19 params[:profile_data][:custom_fields] ||= {}
20 end 20 end
21 Profile.transaction do 21 Profile.transaction do
22 - Image.transaction do  
23 - if @profile_data.update_attributes(params[:profile_data])  
24 - redirect_to :action => 'index', :profile => profile.identifier  
25 - else  
26 - profile.identifier = params[:profile] if profile.identifier.blank? 22 + Image.transaction do
  23 + begin
  24 + @plugins.dispatch(:profile_editor_transaction_extras)
  25 + @profile_data.update_attributes!(params[:profile_data])
  26 + redirect_to :action => 'index', :profile => profile.identifier
  27 + rescue Exception => ex
  28 + profile.identifier = params[:profile] if profile.identifier.blank?
  29 + end
27 end 30 end
28 end 31 end
29 - end  
30 end 32 end
31 end 33 end
32 34
@@ -75,10 +77,51 @@ class ProfileEditorController &lt; MyProfileController @@ -75,10 +77,51 @@ class ProfileEditorController &lt; MyProfileController
75 if request.post? 77 if request.post?
76 if @profile.destroy 78 if @profile.destroy
77 session[:notice] = _('The profile was deleted.') 79 session[:notice] = _('The profile was deleted.')
78 - redirect_to :controller => 'home' 80 + if(params[:return_to])
  81 + redirect_to params[:return_to]
  82 + else
  83 + redirect_to :controller => 'home'
  84 + end
79 else 85 else
80 session[:notice] = _('Could not delete profile') 86 session[:notice] = _('Could not delete profile')
81 end 87 end
82 end 88 end
83 end 89 end
  90 +
  91 + def deactivate_profile
  92 + if environment.admins.include?(current_person)
  93 + profile = environment.profiles.find(params[:id])
  94 + if profile.disable
  95 + profile.save
  96 + session[:notice] = _("The profile '#{profile.name}' was deactivated.")
  97 + else
  98 + session[:notice] = _('Could not deactivate profile.')
  99 + end
  100 + end
  101 +
  102 + redirect_to_previous_location
  103 + end
  104 +
  105 + def activate_profile
  106 + if environment.admins.include?(current_person)
  107 + profile = environment.profiles.find(params[:id])
  108 +
  109 + if profile.enable
  110 + session[:notice] = _("The profile '#{profile.name}' was activated.")
  111 + else
  112 + session[:notice] = _('Could not activate the profile.')
  113 + end
  114 + end
  115 +
  116 + redirect_to_previous_location
  117 + end
  118 +
  119 + protected
  120 +
  121 + def redirect_to_previous_location
  122 + back = request.referer
  123 + back = "/" if back.nil?
  124 +
  125 + redirect_to back
  126 + end
84 end 127 end
app/controllers/my_profile/profile_members_controller.rb
@@ -20,7 +20,7 @@ class ProfileMembersController &lt; MyProfileController @@ -20,7 +20,7 @@ class ProfileMembersController &lt; MyProfileController
20 redirect_to :action => :last_admin 20 redirect_to :action => :last_admin
21 elsif @person.define_roles(@roles, profile) 21 elsif @person.define_roles(@roles, profile)
22 session[:notice] = _('Roles successfuly updated') 22 session[:notice] = _('Roles successfuly updated')
23 - redirect_to :controller => 'profile_editor' 23 + redirect_to :action => 'index'
24 else 24 else
25 session[:notice] = _('Couldn\'t change the roles') 25 session[:notice] = _('Couldn\'t change the roles')
26 redirect_to :action => 'index' 26 redirect_to :action => 'index'
app/controllers/public/account_controller.rb
@@ -104,6 +104,7 @@ class AccountController &lt; ApplicationController @@ -104,6 +104,7 @@ class AccountController &lt; ApplicationController
104 @user.return_to = session[:return_to] 104 @user.return_to = session[:return_to]
105 @person = Person.new(params[:profile_data]) 105 @person = Person.new(params[:profile_data])
106 @person.environment = @user.environment 106 @person.environment = @user.environment
  107 +
107 if request.post? 108 if request.post?
108 if may_be_a_bot 109 if may_be_a_bot
109 set_signup_start_time_for_now 110 set_signup_start_time_for_now
@@ -122,6 +123,14 @@ class AccountController &lt; ApplicationController @@ -122,6 +123,14 @@ class AccountController &lt; ApplicationController
122 invitation.update_attributes!({:friend => @user.person}) 123 invitation.update_attributes!({:friend => @user.person})
123 invitation.finish 124 invitation.finish
124 end 125 end
  126 +
  127 + unless params[:file].nil?
  128 + image = Image::new :uploaded_data=> params[:file][:image]
  129 +
  130 + @user.person.image = image
  131 + @user.person.save
  132 + end
  133 +
125 if @user.activated? 134 if @user.activated?
126 self.current_user = @user 135 self.current_user = @user
127 check_join_in_community(@user) 136 check_join_in_community(@user)
@@ -191,7 +200,7 @@ class AccountController &lt; ApplicationController @@ -191,7 +200,7 @@ class AccountController &lt; ApplicationController
191 else 200 else
192 @change_password.errors[:base] << _('Could not find any user with %s equal to "%s".') % [fields_label, params[:value]] 201 @change_password.errors[:base] << _('Could not find any user with %s equal to "%s".') % [fields_label, params[:value]]
193 end 202 end
194 - rescue ActiveRecord::RecordInvald 203 + rescue ActiveRecord::RecordInvalid
195 @change_password.errors[:base] << _('Could not perform password recovery for the user.') 204 @change_password.errors[:base] << _('Could not perform password recovery for the user.')
196 end 205 end
197 end 206 end
app/controllers/public/chat_controller.rb
@@ -19,9 +19,13 @@ class ChatController &lt; PublicController @@ -19,9 +19,13 @@ class ChatController &lt; PublicController
19 def avatar 19 def avatar
20 profile = environment.profiles.find_by_identifier(params[:id]) 20 profile = environment.profiles.find_by_identifier(params[:id])
21 filename, mimetype = profile_icon(profile, :minor, true) 21 filename, mimetype = profile_icon(profile, :minor, true)
22 - data = File.read(File.join(Rails.root, 'public', filename))  
23 - render :text => data, :layout => false, :content_type => mimetype  
24 - expires_in 24.hours 22 + if filename =~ /^(https?:)?\/\//
  23 + redirect_to filename
  24 + else
  25 + data = File.read(File.join(Rails.root, 'public', filename))
  26 + render :text => data, :layout => false, :content_type => mimetype
  27 + expires_in 24.hours
  28 + end
25 end 29 end
26 30
27 def index 31 def index
app/controllers/public/contact_controller.rb
1 class ContactController < PublicController 1 class ContactController < PublicController
2 2
3 - before_filter :login_required  
4 -  
5 needs_profile 3 needs_profile
6 4
7 def new 5 def new
8 - @contact 6 + @contact = build_contact
9 if request.post? && params[:confirm] == 'true' 7 if request.post? && params[:confirm] == 'true'
10 - @contact = user.build_contact(profile, params[:contact])  
11 @contact.city = (!params[:city].blank? && City.exists?(params[:city])) ? City.find(params[:city]).name : nil 8 @contact.city = (!params[:city].blank? && City.exists?(params[:city])) ? City.find(params[:city]).name : nil
12 @contact.state = (!params[:state].blank? && State.exists?(params[:state])) ? State.find(params[:state]).name : nil 9 @contact.state = (!params[:state].blank? && State.exists?(params[:state])) ? State.find(params[:state]).name : nil
13 if @contact.deliver 10 if @contact.deliver
@@ -16,8 +13,17 @@ class ContactController &lt; PublicController @@ -16,8 +13,17 @@ class ContactController &lt; PublicController
16 else 13 else
17 session[:notice] = _('Contact not sent') 14 session[:notice] = _('Contact not sent')
18 end 15 end
  16 + end
  17 + end
  18 +
  19 + protected
  20 +
  21 + def build_contact
  22 + params[:contact] ||= {}
  23 + if logged_in?
  24 + user.build_contact profile, params[:contact]
19 else 25 else
20 - @contact = user.build_contact(profile) 26 + Contact.new params[:contact].merge(dest: profile)
21 end 27 end
22 end 28 end
23 29
app/controllers/public/content_viewer_controller.rb
@@ -126,7 +126,7 @@ class ContentViewerController &lt; ApplicationController @@ -126,7 +126,7 @@ class ContentViewerController &lt; ApplicationController
126 elsif !@page.display_to?(user) 126 elsif !@page.display_to?(user)
127 if !profile.public? 127 if !profile.public?
128 private_profile_partial_parameters 128 private_profile_partial_parameters
129 - render :template => 'profile/_private_profile', :status => 403 129 + render :template => 'profile/_private_profile', :status => 403, :formats => [:html]
130 allowed = false 130 allowed = false
131 else #if !profile.visible? 131 else #if !profile.visible?
132 render_access_denied 132 render_access_denied
@@ -216,8 +216,6 @@ class ContentViewerController &lt; ApplicationController @@ -216,8 +216,6 @@ class ContentViewerController &lt; ApplicationController
216 if @page.has_posts? 216 if @page.has_posts?
217 posts = get_posts(params[:year], params[:month]) 217 posts = get_posts(params[:year], params[:month])
218 218
219 - posts = posts.includes(:parent, {:profile => [:domains, :environment]}, :author)  
220 -  
221 #FIXME Need to run this before the pagination because this version of 219 #FIXME Need to run this before the pagination because this version of
222 # will_paginate returns a will_paginate collection instead of a 220 # will_paginate returns a will_paginate collection instead of a
223 # relation. 221 # relation.
app/controllers/public/profile_controller.rb
@@ -17,7 +17,11 @@ class ProfileController &lt; PublicController @@ -17,7 +17,11 @@ class ProfileController &lt; PublicController
17 end 17 end
18 @tags = profile.article_tags 18 @tags = profile.article_tags
19 unless profile.display_info_to?(user) 19 unless profile.display_info_to?(user)
20 - profile.visible? ? private_profile : invisible_profile 20 + if profile.visible?
  21 + private_profile
  22 + else
  23 + invisible_profile
  24 + end
21 end 25 end
22 end 26 end
23 27
@@ -61,13 +65,13 @@ class ProfileController &lt; PublicController @@ -61,13 +65,13 @@ class ProfileController &lt; PublicController
61 65
62 def friends 66 def friends
63 if is_cache_expired?(profile.friends_cache_key(params)) 67 if is_cache_expired?(profile.friends_cache_key(params))
64 - @friends = profile.friends.includes(relations_to_include).paginate(:per_page => per_page, :page => params[:npage]) 68 + @friends = profile.friends.includes(relations_to_include).paginate(:per_page => per_page, :page => params[:npage], :total_entries => profile.friends.count)
65 end 69 end
66 end 70 end
67 71
68 def members 72 def members
69 if is_cache_expired?(profile.members_cache_key(params)) 73 if is_cache_expired?(profile.members_cache_key(params))
70 - @members = profile.members_by_name.includes(relations_to_include).paginate(:per_page => members_per_page, :page => params[:npage]) 74 + @members = profile.members_by_name.includes(relations_to_include).paginate(:per_page => members_per_page, :page => params[:npage], :total_entries => profile.members.count)
71 end 75 end
72 end 76 end
73 77
@@ -315,7 +319,7 @@ class ProfileController &lt; PublicController @@ -315,7 +319,7 @@ class ProfileController &lt; PublicController
315 abuse_report = AbuseReport.new(params[:abuse_report]) 319 abuse_report = AbuseReport.new(params[:abuse_report])
316 if !params[:content_type].blank? 320 if !params[:content_type].blank?
317 article = params[:content_type].constantize.find(params[:content_id]) 321 article = params[:content_type].constantize.find(params[:content_id])
318 - abuse_report.content = instance_eval(&article.reported_version) 322 + abuse_report.content = article_reported_version(article)
319 end 323 end
320 324
321 user.register_report(abuse_report, profile) 325 user.register_report(abuse_report, profile)
@@ -394,6 +398,7 @@ class ProfileController &lt; PublicController @@ -394,6 +398,7 @@ class ProfileController &lt; PublicController
394 398
395 def private_profile 399 def private_profile
396 private_profile_partial_parameters 400 private_profile_partial_parameters
  401 + render :action => 'index', :status => 403
397 end 402 end
398 403
399 def invisible_profile 404 def invisible_profile
app/controllers/public/search_controller.rb
@@ -90,10 +90,14 @@ class SearchController &lt; PublicController @@ -90,10 +90,14 @@ class SearchController &lt; PublicController
90 end 90 end
91 91
92 def events 92 def events
93 - year = (params[:year] ? params[:year].to_i : Date.today.year)  
94 - month = (params[:month] ? params[:month].to_i : Date.today.month)  
95 - day = (params[:day] ? params[:day].to_i : Date.today.day)  
96 - @date = build_date(year, month, day) 93 + if params[:year].blank? && params[:year].blank? && params[:day].blank?
  94 + @date = Date.today
  95 + else
  96 + year = (params[:year] ? params[:year].to_i : Date.today.year)
  97 + month = (params[:month] ? params[:month].to_i : Date.today.month)
  98 + day = (params[:day] ? params[:day].to_i : 1)
  99 + @date = build_date(year, month, day)
  100 + end
97 date_range = (@date - 1.month).at_beginning_of_month..(@date + 1.month).at_end_of_month 101 date_range = (@date - 1.month).at_beginning_of_month..(@date + 1.month).at_end_of_month
98 102
99 @events = [] 103 @events = []
app/helpers/application_helper.rb
@@ -304,7 +304,7 @@ module ApplicationHelper @@ -304,7 +304,7 @@ module ApplicationHelper
304 def partial_for_class(klass, prefix=nil, suffix=nil) 304 def partial_for_class(klass, prefix=nil, suffix=nil)
305 raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' if klass.nil? 305 raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' if klass.nil?
306 name = klass.name.underscore 306 name = klass.name.underscore
307 - controller.view_paths.reverse_each do |view_path| 307 + controller.view_paths.each do |view_path|
308 partial = partial_for_class_in_view_path(klass, view_path, prefix, suffix) 308 partial = partial_for_class_in_view_path(klass, view_path, prefix, suffix)
309 return partial if partial 309 return partial if partial
310 end 310 end
@@ -433,19 +433,19 @@ module ApplicationHelper @@ -433,19 +433,19 @@ module ApplicationHelper
433 end 433 end
434 434
435 def theme_site_title 435 def theme_site_title
436 - theme_include('site_title') 436 + @theme_site_title ||= theme_include 'site_title'
437 end 437 end
438 438
439 def theme_header 439 def theme_header
440 - theme_include('header') 440 + @theme_header ||= theme_include 'header'
441 end 441 end
442 442
443 def theme_footer 443 def theme_footer
444 - theme_include('footer') 444 + @theme_footer ||= theme_include 'footer'
445 end 445 end
446 446
447 def theme_extra_navigation 447 def theme_extra_navigation
448 - theme_include('navigation') 448 + @theme_extra_navigation ||= theme_include 'navigation'
449 end 449 end
450 450
451 def is_testing_theme 451 def is_testing_theme
@@ -482,7 +482,12 @@ module ApplicationHelper @@ -482,7 +482,12 @@ module ApplicationHelper
482 '/images/icons-app/enterprise-'+ size.to_s() +'.png' 482 '/images/icons-app/enterprise-'+ size.to_s() +'.png'
483 end 483 end
484 else 484 else
485 - '/images/icons-app/person-'+ size.to_s() +'.png' 485 + pixels = Image.attachment_options[:thumbnails][size].split('x').first
  486 + gravatar_profile_image_url(
  487 + profile.email,
  488 + :size => pixels,
  489 + :d => gravatar_default
  490 + )
486 end 491 end
487 filename = default_or_themed_icon(icon) 492 filename = default_or_themed_icon(icon)
488 end 493 end
@@ -602,7 +607,7 @@ module ApplicationHelper @@ -602,7 +607,7 @@ module ApplicationHelper
602 end 607 end
603 608
604 def gravatar_default 609 def gravatar_default
605 - (respond_to?(:theme_option) && theme_option.present? && theme_option['gravatar']) || NOOSFERO_CONF['gravatar'] 610 + (respond_to?(:theme_option) && theme_option.present? && theme_option['gravatar']) || NOOSFERO_CONF['gravatar'] || 'mm'
606 end 611 end
607 612
608 attr_reader :environment 613 attr_reader :environment
@@ -669,13 +674,14 @@ module ApplicationHelper @@ -669,13 +674,14 @@ module ApplicationHelper
669 html.join "\n" 674 html.join "\n"
670 end 675 end
671 676
  677 + def theme_javascript_src
  678 + script = File.join theme_path, 'theme.js'
  679 + script if File.exists? File.join(Rails.root, 'public', script)
  680 + end
  681 +
672 def theme_javascript_ng 682 def theme_javascript_ng
673 - script = File.join(theme_path, 'theme.js')  
674 - if File.exists?(File.join(Rails.root, 'public', script))  
675 - javascript_include_tag script  
676 - else  
677 - nil  
678 - end 683 + script = theme_javascript_src
  684 + javascript_include_tag script if script
679 end 685 end
680 686
681 def file_field_or_thumbnail(label, image, i) 687 def file_field_or_thumbnail(label, image, i)
@@ -856,8 +862,9 @@ module ApplicationHelper @@ -856,8 +862,9 @@ module ApplicationHelper
856 end 862 end
857 863
858 def base_url 864 def base_url
859 - environment.top_url 865 + environment.top_url(request.scheme)
860 end 866 end
  867 + alias :top_url :base_url
861 868
862 def helper_for_article(article) 869 def helper_for_article(article)
863 article_helper = ActionView::Base.new 870 article_helper = ActionView::Base.new
@@ -902,13 +909,15 @@ module ApplicationHelper @@ -902,13 +909,15 @@ module ApplicationHelper
902 end 909 end
903 910
904 def page_title 911 def page_title
905 - (@page ? @page.title + ' - ' : '') +  
906 - (@topic ? @topic.title + ' - ' : '') +  
907 - (@section ? @section.title + ' - ' : '') +  
908 - (@toc ? _('Online Manual') + ' - ' : '') +  
909 - (controller.controller_name == 'chat' ? _('Chat') + ' - ' : '') +  
910 - (profile ? profile.short_name : environment.name) +  
911 - (@category ? " - #{@category.full_name}" : '') 912 + CGI.escapeHTML(
  913 + (@page ? @page.title + ' - ' : '') +
  914 + (@topic ? @topic.title + ' - ' : '') +
  915 + (@section ? @section.title + ' - ' : '') +
  916 + (@toc ? _('Online Manual') + ' - ' : '') +
  917 + (controller.controller_name == 'chat' ? _('Chat') + ' - ' : '') +
  918 + (profile ? profile.short_name : environment.name) +
  919 + (@category ? " - #{@category.full_name}" : '')
  920 + )
912 end 921 end
913 922
914 # DEPRECATED. Do not use this. 923 # DEPRECATED. Do not use this.
@@ -937,9 +946,9 @@ module ApplicationHelper @@ -937,9 +946,9 @@ module ApplicationHelper
937 # from Article model for an ArticleBlock. 946 # from Article model for an ArticleBlock.
938 def reference_to_article(text, article, anchor=nil) 947 def reference_to_article(text, article, anchor=nil)
939 if article.profile.domains.empty? 948 if article.profile.domains.empty?
940 - href = "/#{article.url[:profile]}/" 949 + href = "#{Noosfero.root}/#{article.url[:profile]}/"
941 else 950 else
942 - href = "http://#{article.profile.domains.first.name}/" 951 + href = "http://#{article.profile.domains.first.name}#{Noosfero.root}/"
943 end 952 end
944 href += article.url[:page].join('/') 953 href += article.url[:page].join('/')
945 href += '#' + anchor if anchor 954 href += '#' + anchor if anchor
@@ -1280,11 +1289,13 @@ module ApplicationHelper @@ -1280,11 +1289,13 @@ module ApplicationHelper
1280 end 1289 end
1281 1290
1282 def delete_article_message(article) 1291 def delete_article_message(article)
1283 - if article.folder?  
1284 - _("Are you sure that you want to remove the folder \"#{article.name}\"? Note that all the items inside it will also be removed!")  
1285 - else  
1286 - _("Are you sure that you want to remove the item \"#{article.name}\"?")  
1287 - end 1292 + CGI.escapeHTML(
  1293 + if article.folder?
  1294 + _("Are you sure that you want to remove the folder \"%s\"? Note that all the items inside it will also be removed!") % article.name
  1295 + else
  1296 + _("Are you sure that you want to remove the item \"%s\"?") % article.name
  1297 + end
  1298 + )
1288 end 1299 end
1289 1300
1290 def expirable_link_to(expired, content, url, options = {}) 1301 def expirable_link_to(expired, content, url, options = {})
@@ -1301,7 +1312,7 @@ module ApplicationHelper @@ -1301,7 +1312,7 @@ module ApplicationHelper
1301 end 1312 end
1302 1313
1303 def template_options(kind, field_name) 1314 def template_options(kind, field_name)
1304 - templates = environment.send(kind).templates.order('name') 1315 + templates = environment.send(kind).templates
1305 return '' if templates.count == 0 1316 return '' if templates.count == 0
1306 if templates.count == 1 1317 if templates.count == 1
1307 if templates.first.custom_fields == {} 1318 if templates.first.custom_fields == {}
@@ -1315,10 +1326,16 @@ module ApplicationHelper @@ -1315,10 +1326,16 @@ module ApplicationHelper
1315 content_tag('div', custom_fields) 1326 content_tag('div', custom_fields)
1316 end 1327 end
1317 else 1328 else
1318 - options = options_for_select(templates.collect{ |template| [template.name, template.id]})  
1319 - content_tag('div',  
1320 - content_tag('div', content_tag('label', _('Profile organization'), :class => 'formlabel') + (select_tag 'profile_data[template_id]', options, :onchange => 'show_fields_for_template(this);')),  
1321 - :id => 'template-options') 1329 + radios = templates.map do |template|
  1330 + content_tag('li', labelled_radio_button(link_to(template.name, template.url, :target => '_blank'), "#{field_name}[template_id]", template.id, environment.is_default_template?(template)))
  1331 + end.join("\n")
  1332 +
  1333 + content_tag('div', content_tag('label', _('Profile organization'), :for => 'template-options', :class => 'formlabel') +
  1334 + content_tag('p', _('Your profile will be created according to the selected template. Click on the options to view them.'), :style => 'margin: 5px 15px;padding: 0px 10px;') +
  1335 + content_tag('ul', radios, :style => 'list-style: none; padding-left: 20px; margin-top: 0.5em;'),
  1336 + :id => 'template-options',
  1337 + :style => 'margin-top: 1em'
  1338 + )
1322 end 1339 end
1323 end 1340 end
1324 1341
@@ -1375,7 +1392,7 @@ module ApplicationHelper @@ -1375,7 +1392,7 @@ module ApplicationHelper
1375 # are old things that do not support it we are keeping this hot spot. 1392 # are old things that do not support it we are keeping this hot spot.
1376 html = @plugins.pipeline(:parse_content, html, source).first 1393 html = @plugins.pipeline(:parse_content, html, source).first
1377 end 1394 end
1378 - html 1395 + html && html.html_safe
1379 end 1396 end
1380 1397
1381 def convert_macro(html, source) 1398 def convert_macro(html, source)
app/helpers/article_helper.rb
@@ -3,6 +3,12 @@ module ArticleHelper @@ -3,6 +3,12 @@ module ArticleHelper
3 include PrototypeHelper 3 include PrototypeHelper
4 include TokenHelper 4 include TokenHelper
5 5
  6 + def article_reported_version(article)
  7 + search_path = Rails.root.join('app', 'views', 'shared', 'reported_versions')
  8 + partial_path = File.join('shared', 'reported_versions', 'profile', partial_for_class_in_view_path(article.class, search_path))
  9 + render_to_string(:partial => partial_path, :locals => {:article => article})
  10 + end
  11 +
6 def custom_options_for_article(article, tokenized_children) 12 def custom_options_for_article(article, tokenized_children)
7 @article = article 13 @article = article
8 14
@@ -71,12 +77,59 @@ module ArticleHelper @@ -71,12 +77,59 @@ module ArticleHelper
71 content_tag('div', 77 content_tag('div',
72 radio_button(:article, :published, false) + 78 radio_button(:article, :published, false) +
73 content_tag('label', _('Private'), :for => 'article_published_false', :id => "label_private") 79 content_tag('label', _('Private'), :for => 'article_published_false', :id => "label_private")
74 - ) +  
75 - (article.profile.community? ? content_tag('div',  
76 - content_tag('label', _('Fill in the search field to add the exception users to see this content'), :id => "text-input-search-exception-users") +  
77 - token_input_field_tag(:q, 'search-article-privacy-exceptions', {:action => 'search_article_privacy_exceptions'},  
78 - {:focus => false, :hint_text => _('Type in a search term for a user'), :pre_populate => tokenized_children})) :  
79 - '')) 80 + ) +
  81 + privacity_exceptions(article, tokenized_children)
  82 + )
  83 + end
  84 +
  85 + def privacity_exceptions(article, tokenized_children)
  86 + content_tag('div',
  87 + content_tag('div',
  88 + (
  89 + if article.profile
  90 + add_option_to_followers(article, tokenized_children)
  91 + else
  92 + ''
  93 + end
  94 + )
  95 + ),
  96 + :style => "margin-left:10px"
  97 + )
  98 + end
  99 +
  100 + def add_option_to_followers(article, tokenized_children)
  101 + label_message = article.profile.organization? ? _('For all community members') : _('For all your friends')
  102 +
  103 + check_box(
  104 + :article,
  105 + :show_to_followers,
  106 + {:class => "custom_privacy_option"}
  107 + ) +
  108 + content_tag(
  109 + 'label',
  110 + label_message,
  111 + :for => 'article_show_to_followers',
  112 + :id => 'label_show_to_followers'
  113 + ) +
  114 + (article.profile.community? ?
  115 + content_tag(
  116 + 'div',
  117 + content_tag(
  118 + 'label',
  119 + _('Fill in the search field to add the exception users to see this content'),
  120 + :id => "text-input-search-exception-users"
  121 + ) +
  122 + token_input_field_tag(
  123 + :q,
  124 + 'search-article-privacy-exceptions',
  125 + {:action => 'search_article_privacy_exceptions'},
  126 + {
  127 + :focus => false,
  128 + :hint_text => _('Type in a search term for a user'),
  129 + :pre_populate => tokenized_children
  130 + }
  131 + )
  132 + ) : '')
80 end 133 end
81 134
82 def prepare_to_token_input(array) 135 def prepare_to_token_input(array)
app/helpers/boxes_helper.rb
@@ -170,49 +170,54 @@ module BoxesHelper @@ -170,49 +170,54 @@ module BoxesHelper
170 else 170 else
171 "before-block-#{block.id}" 171 "before-block-#{block.id}"
172 end 172 end
173 -  
174 - content_tag('div', '&nbsp;', :id => id, :class => 'block-target' ) + drop_receiving_element(id, :url => { :action => 'move_block', :target => id }, :accept => box.acceptable_blocks, :hoverclass => 'block-target-hover') 173 + if block.nil? or modifiable?(block)
  174 + content_tag('div', '&nbsp;', :id => id, :class => 'block-target' ) + drop_receiving_element(id, :url => { :action => 'move_block', :target => id }, :accept => box.acceptable_blocks, :hoverclass => 'block-target-hover')
  175 + else
  176 + ""
  177 + end
175 end 178 end
176 179
177 # makes the given block draggable so it can be moved away. 180 # makes the given block draggable so it can be moved away.
178 def block_handle(block) 181 def block_handle(block)
179 - draggable_element("block-#{block.id}", :revert => true) 182 + modifiable?(block) ? draggable_element("block-#{block.id}", :revert => true) : ""
180 end 183 end
181 184
182 def block_edit_buttons(block) 185 def block_edit_buttons(block)
183 buttons = [] 186 buttons = []
184 nowhere = 'javascript: return false;' 187 nowhere = 'javascript: return false;'
185 188
186 - if block.first?  
187 - buttons << icon_button('up-disabled', _("Can't move up anymore."), nowhere)  
188 - else  
189 - buttons << icon_button('up', _('Move block up'), { :action => 'move_block_up', :id => block.id }, { :method => 'post' })  
190 - end 189 + if modifiable?(block)
  190 + if block.first?
  191 + buttons << icon_button('up-disabled', _("Can't move up anymore."), nowhere)
  192 + else
  193 + buttons << icon_button('up', _('Move block up'), { :action => 'move_block_up', :id => block.id }, { :method => 'post' })
  194 + end
191 195
192 - if block.last?  
193 - buttons << icon_button('down-disabled', _("Can't move down anymore."), nowhere)  
194 - else  
195 - buttons << icon_button(:down, _('Move block down'), { :action => 'move_block_down' ,:id => block.id }, { :method => 'post'})  
196 - end 196 + if block.last?
  197 + buttons << icon_button('down-disabled', _("Can't move down anymore."), nowhere)
  198 + else
  199 + buttons << icon_button(:down, _('Move block down'), { :action => 'move_block_down' ,:id => block.id }, { :method => 'post'})
  200 + end
197 201
198 - holder = block.owner  
199 - # move to opposite side  
200 - # FIXME too much hardcoded stuff  
201 - if holder.layout_template == 'default'  
202 - if block.box.position == 2 # area 2, left side => move to right side  
203 - buttons << icon_button('right', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[2].id.to_s, :id => block.id }, :method => 'post' )  
204 - elsif block.box.position == 3 # area 3, right side => move to left side  
205 - buttons << icon_button('left', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[1].id.to_s, :id => block.id }, :method => 'post' ) 202 + holder = block.owner
  203 + # move to opposite side
  204 + # FIXME too much hardcoded stuff
  205 + if holder.layout_template == 'default'
  206 + if block.box.position == 2 # area 2, left side => move to right side
  207 + buttons << icon_button('right', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[2].id.to_s, :id => block.id }, :method => 'post' )
  208 + elsif block.box.position == 3 # area 3, right side => move to left side
  209 + buttons << icon_button('left', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[1].id.to_s, :id => block.id }, :method => 'post' )
  210 + end
206 end 211 end
207 - end  
208 212
209 - if block.editable?  
210 - buttons << colorbox_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id })  
211 - end 213 + if block.editable?
  214 + buttons << colorbox_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id })
  215 + end
212 216
213 - if !block.main?  
214 - buttons << icon_button(:delete, _('Remove block'), { :action => 'remove', :id => block.id }, { :method => 'post', :confirm => _('Are you sure you want to remove this block?')})  
215 - buttons << icon_button(:clone, _('Clone'), { :action => 'clone_block', :id => block.id }, { :method => 'post' }) 217 + if !block.main?
  218 + buttons << icon_button(:delete, _('Remove block'), { :action => 'remove', :id => block.id }, { :method => 'post', :confirm => _('Are you sure you want to remove this block?')})
  219 + buttons << icon_button(:clone, _('Clone'), { :action => 'clone_block', :id => block.id }, { :method => 'post' })
  220 + end
216 end 221 end
217 222
218 if block.respond_to?(:help) 223 if block.respond_to?(:help)
@@ -248,5 +253,7 @@ module BoxesHelper @@ -248,5 +253,7 @@ module BoxesHelper
248 classes 253 classes
249 end 254 end
250 255
251 - 256 + def modifiable?(block)
  257 + return !block.fixed || environment.admins.include?(user)
  258 + end
252 end 259 end
app/helpers/content_viewer_helper.rb
@@ -10,7 +10,7 @@ module ContentViewerHelper @@ -10,7 +10,7 @@ module ContentViewerHelper
10 end 10 end
11 11
12 def number_of_comments(article) 12 def number_of_comments(article)
13 - display_number_of_comments(article.comments_count - article.spam_comments_count) 13 + display_number_of_comments(article.comments_count - article.spam_comments_count.to_i)
14 end 14 end
15 15
16 def article_title(article, args = {}) 16 def article_title(article, args = {})
@@ -45,7 +45,7 @@ module ContentViewerHelper @@ -45,7 +45,7 @@ module ContentViewerHelper
45 { article.environment.locales[translation.language] => { :href => url_for(translation.url) } } 45 { article.environment.locales[translation.language] => { :href => url_for(translation.url) } }
46 end 46 end
47 content_tag(:div, link_to(_('Translations'), '#', 47 content_tag(:div, link_to(_('Translations'), '#',
48 - :onmouseover => "toggleSubmenu(this, '#{_('Translations')}', #{links.to_json}); return false", 48 + :onmouseover => "toggleSubmenu(this, '#{_('Translations')}', #{CGI::escape_html(links.to_json)}); return false",
49 :class => 'article-translations-menu simplemenu-trigger up'), 49 :class => 'article-translations-menu simplemenu-trigger up'),
50 :class => 'article-translations') 50 :class => 'article-translations')
51 end 51 end
app/helpers/layout_helper.rb
@@ -2,12 +2,31 @@ module LayoutHelper @@ -2,12 +2,31 @@ module LayoutHelper
2 2
3 def body_classes 3 def body_classes
4 # Identify the current controller and action for the CSS: 4 # Identify the current controller and action for the CSS:
  5 + (logged_in? ? " logged-in" : "") +
5 " controller-#{controller.controller_name}" + 6 " controller-#{controller.controller_name}" +
6 " action-#{controller.controller_name}-#{controller.action_name}" + 7 " action-#{controller.controller_name}-#{controller.action_name}" +
7 " template-#{@layout_template || if profile.blank? then 'default' else profile.layout_template end}" + 8 " template-#{@layout_template || if profile.blank? then 'default' else profile.layout_template end}" +
8 (!profile.nil? && profile.is_on_homepage?(request.path,@page) ? " profile-homepage" : "") 9 (!profile.nil? && profile.is_on_homepage?(request.path,@page) ? " profile-homepage" : "")
9 end 10 end
10 11
  12 + def html_tag_classes
  13 + [
  14 + body_classes, (
  15 + profile.blank? ? nil : [
  16 + 'profile-type-is-' + profile.class.name.downcase,
  17 + 'profile-name-is-' + profile.identifier,
  18 + ]
  19 + ), 'theme-' + current_theme,
  20 + @plugins.dispatch(:html_tag_classes).map do |content|
  21 + if content.respond_to?(:call)
  22 + instance_exec(&content)
  23 + else
  24 + content.html_safe
  25 + end
  26 + end
  27 + ].flatten.compact.join(' ')
  28 + end
  29 +
11 def noosfero_javascript 30 def noosfero_javascript
12 plugins_javascripts = @plugins.map { |plugin| [plugin.js_files].flatten.map { |js| plugin.class.public_path(js) } }.flatten 31 plugins_javascripts = @plugins.map { |plugin| [plugin.js_files].flatten.map { |js| plugin.class.public_path(js) } }.flatten
13 32
@@ -17,6 +36,8 @@ module LayoutHelper @@ -17,6 +36,8 @@ module LayoutHelper
17 unless plugins_javascripts.empty? 36 unless plugins_javascripts.empty?
18 output += javascript_include_tag plugins_javascripts, :cache => "cache/plugins-#{Digest::MD5.hexdigest plugins_javascripts.to_s}" 37 output += javascript_include_tag plugins_javascripts, :cache => "cache/plugins-#{Digest::MD5.hexdigest plugins_javascripts.to_s}"
19 end 38 end
  39 + output += theme_javascript_ng.to_s
  40 +
20 output 41 output
21 end 42 end
22 43
@@ -84,6 +105,10 @@ module LayoutHelper @@ -84,6 +105,10 @@ module LayoutHelper
84 theme_path + '/style.css' 105 theme_path + '/style.css'
85 end 106 end
86 107
  108 + def layout_template
  109 + if profile then profile.layout_template else environment.layout_template end
  110 + end
  111 +
87 def addthis_javascript 112 def addthis_javascript
88 if NOOSFERO_CONF['addthis_enabled'] 113 if NOOSFERO_CONF['addthis_enabled']
89 '<script src="https://s7.addthis.com/js/152/addthis_widget.js"></script>' 114 '<script src="https://s7.addthis.com/js/152/addthis_widget.js"></script>'
@@ -91,7 +116,7 @@ module LayoutHelper @@ -91,7 +116,7 @@ module LayoutHelper
91 end 116 end
92 117
93 def meta_description_tag(article=nil) 118 def meta_description_tag(article=nil)
94 - article ? truncate(strip_tags(article.body.to_s), :length => 200) : environment.name 119 + article ? CGI.escapeHTML(truncate(strip_tags(article.body.to_s), :length => 200)) : environment.name
95 end 120 end
96 end 121 end
97 122
app/helpers/person_notifier_helper.rb
@@ -1,15 +0,0 @@ @@ -1,15 +0,0 @@
1 -module PersonNotifierHelper  
2 -  
3 - include ApplicationHelper  
4 -  
5 - private  
6 -  
7 - def path_to_image(source)  
8 - top_url + source  
9 - end  
10 -  
11 - def top_url  
12 - top_url = @profile.environment ? @profile.environment.top_url : ''  
13 - end  
14 -  
15 -end  
app/helpers/profile_helper.rb
1 module ProfileHelper 1 module ProfileHelper
2 2
3 - def display_field(title, profile, field, force = false) 3 + COMMON_CATEGORIES = ActiveSupport::OrderedHash.new
  4 + COMMON_CATEGORIES[:content] = [:blogs, :image_galleries, :events, :article_tags]
  5 + COMMON_CATEGORIES[:interests] = [:interests]
  6 + COMMON_CATEGORIES[:general] = nil
  7 +
  8 + PERSON_CATEGORIES = ActiveSupport::OrderedHash.new
  9 + PERSON_CATEGORIES[:basic_information] = [:nickname, :sex, :birth_date, :location, :privacy_setting, :created_at]
  10 + PERSON_CATEGORIES[:contact] = [:contact_phone, :cell_phone, :comercial_phone, :contact_information, :email, :personal_website, :jabber_id]
  11 + PERSON_CATEGORIES[:location] = [:address, :address_reference, :zip_code, :city, :state, :district, :country, :nationality]
  12 + PERSON_CATEGORIES[:work] = [:organization, :organization_website, :professional_activity]
  13 + PERSON_CATEGORIES[:study] = [:schooling, :formation, :area_of_study]
  14 + PERSON_CATEGORIES[:network] = [:friends, :communities, :enterprises]
  15 + PERSON_CATEGORIES.merge!(COMMON_CATEGORIES)
  16 +
  17 + ORGANIZATION_CATEGORIES = ActiveSupport::OrderedHash.new
  18 + ORGANIZATION_CATEGORIES[:basic_information] = [:display_name, :created_at, :foundation_year, :type, :language, :members_count, :location, :address_reference, :historic_and_current_context, :admins]
  19 + ORGANIZATION_CATEGORIES[:contact] = [:contact_person, :contact_phone, :contact_email, :organization_website, :jabber_id]
  20 + ORGANIZATION_CATEGORIES[:economic] = [:business_name, :acronym, :economic_activity, :legal_form, :products, :activities_short_description, :management_information]
  21 + ORGANIZATION_CATEGORIES.merge!(COMMON_CATEGORIES)
  22 +
  23 + CATEGORY_MAP = ActiveSupport::OrderedHash.new
  24 + CATEGORY_MAP[:person] = PERSON_CATEGORIES
  25 + CATEGORY_MAP[:organization] = ORGANIZATION_CATEGORIES
  26 +
  27 + FORCE = {
  28 + :person => [:privacy_setting],
  29 + :organization => [:privacy_setting, :location],
  30 + }
  31 +
  32 + MULTIPLE = {
  33 + :person => [:blogs, :image_galleries, :interests],
  34 + :organization => [:blogs, :image_galleries, :interests],
  35 + }
  36 +
  37 + CUSTOM_LABELS = {
  38 + :zip_code => _('ZIP code'),
  39 + :email => _('e-Mail'),
  40 + :jabber_id => _('Jabber'),
  41 + :birth_date => _('Date of birth'),
  42 + :created_at => _('Profile created at'),
  43 + :members_count => _('Members'),
  44 + :privacy_setting => _('Privacy setting'),
  45 + :article_tags => _('Tags')
  46 + }
  47 +
  48 + EXCEPTION = {
  49 + :person => [:image, :preferred_domain, :description, :tag_list],
  50 + :organization => [:image, :preferred_domain, :description, :tag_list, :address, :zip_code, :city, :state, :country, :district]
  51 + }
  52 +
  53 + def general_fields
  54 + categorized_fields = CATEGORY_MAP[kind].values.flatten
  55 + profile.class.fields.map(&:to_sym) - categorized_fields - EXCEPTION[kind]
  56 + end
  57 +
  58 + def kind
  59 + if profile.kind_of?(Person)
  60 + :person
  61 + else
  62 + :organization
  63 + end
  64 + end
  65 +
  66 + def title(field, entry = nil)
  67 + return self.send("#{field}_custom_title", entry) if MULTIPLE[kind].include?(field) && entry.present?
  68 + CUSTOM_LABELS[field.to_sym] || _(field.to_s.humanize)
  69 + end
  70 +
  71 + def display_field(field)
  72 + force = FORCE[kind].include?(field)
  73 + multiple = MULTIPLE[kind].include?(field)
4 unless force || profile.may_display_field_to?(field, user) 74 unless force || profile.may_display_field_to?(field, user)
5 return '' 75 return ''
6 end 76 end
7 - value = profile.send(field)  
8 - if !value.blank?  
9 - if block_given?  
10 - value = yield(value)  
11 - end  
12 - content_tag('tr', content_tag('td', title, :class => 'field-name') + content_tag('td', value)) 77 + value = begin profile.send(field) rescue nil end
  78 + return '' if value.blank?
  79 + if value.kind_of?(Hash)
  80 + content = self.send("treat_#{field}", value)
  81 + content_tag('tr', content_tag('td', title(field), :class => 'field-name') + content_tag('td', content))
13 else 82 else
14 - '' 83 + entries = multiple ? value : [] << value
  84 + entries.map do |entry|
  85 + content = self.send("treat_#{field}", entry)
  86 + unless content.blank?
  87 + content_tag('tr', content_tag('td', title(field, entry), :class => 'field-name') + content_tag('td', content))
  88 + end
  89 + end.join("\n")
15 end 90 end
16 end 91 end
17 92
18 - def display_contact(profile)  
19 - fields = []  
20 - fields << display_field(_('Address:'), profile, :address).html_safe  
21 - fields << display_field(_('ZIP code:'), profile, :zip_code).html_safe  
22 - fields << display_field(_('Contact phone:'), profile, :contact_phone).html_safe  
23 - fields << display_field(_('e-Mail:'), profile, :email) { |email| link_to_email(email) }.html_safe  
24 - fields << display_field(_('Personal website:'), profile, :personal_website).html_safe  
25 - fields << display_field(_('Jabber:'), profile, :jabber_id).html_safe  
26 - if fields.reject!(&:blank?).empty?  
27 - ''  
28 - else  
29 - content_tag('tr', content_tag('th', _('Contact'), { :colspan => 2 })) + fields.join.html_safe 93 + def treat_email(email)
  94 + link_to_email(email)
  95 + end
  96 +
  97 + def treat_organization_website(url)
  98 + link_to(url, url)
  99 + end
  100 +
  101 + def treat_sex(gender)
  102 + { 'male' => _('Male'), 'female' => _('Female') }[gender]
  103 + end
  104 +
  105 + def treat_date(date)
  106 + show_date(date.to_date)
  107 + end
  108 + alias :treat_birth_date :treat_date
  109 + alias :treat_created_at :treat_date
  110 +
  111 + def treat_friends(friends)
  112 + link_to friends.count, :controller => 'profile', :action => 'friends'
  113 + end
  114 +
  115 + def treat_communities(communities)
  116 + link_to communities.count, :controller => "profile", :action => 'communities'
  117 + end
  118 +
  119 + def treat_enterprises(enterprises)
  120 + if environment.disabled?('disable_asset_enterprises')
  121 + link_to enterprises.count, :controller => "profile", :action => 'enterprises'
  122 + end
  123 + end
  124 +
  125 + def treat_members_count(count)
  126 + link_to count, :controller => 'profile', :action => 'members'
  127 + end
  128 +
  129 + def treat_products(products)
  130 + if profile.kind_of?(Enterprise) && profile.environment.enabled?('products_for_enterprises')
  131 + link_to _('Products/Services'), :controller => 'catalog', :action => 'index'
30 end 132 end
31 end 133 end
32 134
33 - def display_work_info(profile)  
34 - organization = display_field(_('Organization:'), profile, :organization)  
35 - organization_site = display_field(_('Organization website:'), profile, :organization_website) { |url| link_to(url, url) }  
36 - if organization.blank? && organization_site.blank?  
37 - '' 135 + def treat_admins(admins)
  136 + profile.admins.map { |admin| link_to(admin.short_name, admin.url)}.join(', ')
  137 + end
  138 +
  139 + def treat_blogs(blog)
  140 + link_to(n_('One post', '%{num} posts', blog.posts.published.count) % { :num => blog.posts.published.count }, blog.url)
  141 + end
  142 +
  143 + def treat_image_galleries(gallery)
  144 + link_to(n_('One picture', '%{num} pictures', gallery.images.published.count) % { :num => gallery.images.published.count }, gallery.url)
  145 + end
  146 +
  147 + def treat_events(events)
  148 + link_to events.published.count, :controller => 'events', :action => 'events'
  149 + end
  150 +
  151 + def treat_article_tags(tags)
  152 + tag_cloud @tags, :id, { :action => 'tags' }, :max_size => 18, :min_size => 10
  153 + end
  154 +
  155 + def treat_interests(interest)
  156 + link_to interest.name, :controller => 'search', :action => 'category_index', :category_path => interest.explode_path
  157 + end
  158 +
  159 + def article_custom_title(article)
  160 + article.name
  161 + end
  162 + alias :blogs_custom_title :article_custom_title
  163 + alias :image_galleries_custom_title :article_custom_title
  164 +
  165 + def interests_custom_title(interest)
  166 + ''
  167 + end
  168 +
  169 + def method_missing(method, *args, &block)
  170 + if method.to_s =~ /^treat_(.+)$/
  171 + args[0]
  172 + elsif method.to_s =~ /^display_(.+)$/ && CATEGORY_MAP[kind].has_key?($1.to_sym)
  173 + category = $1.to_sym
  174 + fields = category == :general ? general_fields : CATEGORY_MAP[kind][category]
  175 + contents = []
  176 +
  177 + fields.each do |field|
  178 + contents << display_field(field).html_safe
  179 + end
  180 +
  181 + contents = contents.delete_if(&:blank?)
  182 +
  183 + unless contents.empty?
  184 + content_tag('tr', content_tag('th', title(category), { :colspan => 2 })) + contents.join.html_safe
  185 + else
  186 + ''
  187 + end
38 else 188 else
39 - content_tag('tr', content_tag('th', _('Work'), { :colspan => 2 })) + organization + organization_site 189 + super
40 end 190 end
41 end 191 end
42 192
app/helpers/role_helper.rb
1 module RoleHelper 1 module RoleHelper
  2 +
  3 + def role_available_permissions(role)
  4 + role.kind == "Environment" ? ['Environment', 'Profile'] : [role.kind]
  5 + end
  6 +
2 end 7 end
app/helpers/search_helper.rb
@@ -21,6 +21,12 @@ module SearchHelper @@ -21,6 +21,12 @@ module SearchHelper
21 'more_comments' => _('More comments') 21 'more_comments' => _('More comments')
22 } 22 }
23 23
  24 + COMMON_PROFILE_LIST_BLOCK = [
  25 + :enterprises,
  26 + :people,
  27 + :communities
  28 + ]
  29 +
24 # FIXME remove it after search_controler refactored 30 # FIXME remove it after search_controler refactored
25 include EventsHelper 31 include EventsHelper
26 32
@@ -94,7 +100,7 @@ module SearchHelper @@ -94,7 +100,7 @@ module SearchHelper
94 compact_link = display?(asset, :compact) ? (display == 'compact' ? _('Compact') : link_to(_('Compact'), params.merge(:display => 'compact'))) : nil 100 compact_link = display?(asset, :compact) ? (display == 'compact' ? _('Compact') : link_to(_('Compact'), params.merge(:display => 'compact'))) : nil
95 map_link = display?(asset, :map) ? (display == 'map' ? _('Map') : link_to(_('Map'), params.merge(:display => 'map'))) : nil 101 map_link = display?(asset, :map) ? (display == 'map' ? _('Map') : link_to(_('Map'), params.merge(:display => 'map'))) : nil
96 full_link = display?(asset, :full) ? (display == 'full' ? _('Full') : link_to(_('Full'), params.merge(:display => 'full'))) : nil 102 full_link = display?(asset, :full) ? (display == 'full' ? _('Full') : link_to(_('Full'), params.merge(:display => 'full'))) : nil
97 - content_tag('div', 103 + content_tag('div',
98 content_tag('strong', _('Display')) + ': ' + [compact_link, map_link, full_link].compact.join(' | ').html_safe, 104 content_tag('strong', _('Display')) + ': ' + [compact_link, map_link, full_link].compact.join(' | ').html_safe,
99 :class => 'search-customize-options' 105 :class => 'search-customize-options'
100 ) 106 )
app/helpers/sweeper_helper.rb
@@ -56,12 +56,12 @@ module SweeperHelper @@ -56,12 +56,12 @@ module SweeperHelper
56 if profile 56 if profile
57 profile.blocks.each {|block| 57 profile.blocks.each {|block|
58 conditions = block.class.expire_on 58 conditions = block.class.expire_on
59 - blocks_to_expire << block unless (conditions[:profile] & causes).empty? 59 + blocks_to_expire << block unless (conditions[:profile] & causes).blank?
60 } 60 }
61 end 61 end
62 environment.blocks.each {|block| 62 environment.blocks.each {|block|
63 conditions = block.class.expire_on 63 conditions = block.class.expire_on
64 - blocks_to_expire << block unless (conditions[:environment] & causes).empty? 64 + blocks_to_expire << block unless (conditions[:environment] & causes).blank?
65 } 65 }
66 66
67 blocks_to_expire.uniq! 67 blocks_to_expire.uniq!
app/helpers/tinymce_helper.rb 0 → 100644
@@ -0,0 +1,51 @@ @@ -0,0 +1,51 @@
  1 +module TinymceHelper
  2 + include MacrosHelper
  3 +
  4 + def tinymce_js
  5 + output = ''
  6 + output += javascript_include_tag 'tinymce/js/tinymce/tinymce.min.js'
  7 + output += javascript_include_tag 'tinymce/js/tinymce/jquery.tinymce.min.js'
  8 + output += javascript_include_tag 'tinymce.js'
  9 + output += include_macro_js_files.to_s
  10 + output
  11 + end
  12 +
  13 + def tinymce_init_js options = {}
  14 + options.merge! :document_base_url => top_url,
  15 + :content_css => "/stylesheets/tinymce.css,#{macro_css_files}",
  16 + :plugins => %w[compat3x advlist autolink lists link image charmap print preview hr anchor pagebreak
  17 + searchreplace wordcount visualblocks visualchars code fullscreen
  18 + insertdatetime media nonbreaking save table contextmenu directionality
  19 + emoticons template paste textcolor colorpicker textpattern],
  20 + :language => tinymce_language
  21 +
  22 + options[:toolbar1] = "insertfile undo redo | copy paste | bold italic underline | styleselect fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image"
  23 + if options[:mode] == 'simple'
  24 + options[:menubar] = false
  25 + else
  26 + options[:menubar] = 'edit insert view tools'
  27 + options[:toolbar2] = 'print preview code media | table'
  28 +
  29 + options[:toolbar2] += ' | macros'
  30 + macros_with_buttons.each do |macro|
  31 + options[:toolbar2] += " #{macro.identifier}"
  32 + end
  33 + end
  34 +
  35 + options[:macros_setup] = macros_with_buttons.map do |macro|
  36 + <<-EOS
  37 + ed.addButton('#{macro.identifier}', {
  38 + title: #{macro_title(macro).to_json},
  39 + onclick: #{generate_macro_config_dialog macro},
  40 + image : '#{macro.configuration[:icon_path]}'
  41 + });
  42 + EOS
  43 + end
  44 +
  45 + #cleanup non tinymce options
  46 + options = options.except :mode
  47 +
  48 + "noosfero.tinymce.init(#{options.to_json})"
  49 + end
  50 +
  51 +end
app/models/article.rb
@@ -2,7 +2,14 @@ require &#39;hpricot&#39; @@ -2,7 +2,14 @@ require &#39;hpricot&#39;
2 2
3 class Article < ActiveRecord::Base 3 class Article < ActiveRecord::Base
4 4
5 - attr_accessible :name, :body, :abstract, :profile, :tag_list, :parent, :allow_members_to_edit, :translation_of_id, :language, :license_id, :parent_id, :display_posts_in_current_language, :category_ids, :posts_per_page, :moderate_comments, :accept_comments, :feed, :published, :source, :highlighted, :notify_comments, :display_hits, :slug, :external_feed_builder, :display_versions, :external_link, :image_builder 5 + attr_accessible :name, :body, :abstract, :profile, :tag_list, :parent,
  6 + :allow_members_to_edit, :translation_of_id, :language,
  7 + :license_id, :parent_id, :display_posts_in_current_language,
  8 + :category_ids, :posts_per_page, :moderate_comments,
  9 + :accept_comments, :feed, :published, :source,
  10 + :highlighted, :notify_comments, :display_hits, :slug,
  11 + :external_feed_builder, :display_versions, :external_link,
  12 + :image_builder, :show_to_followers
6 13
7 acts_as_having_image 14 acts_as_having_image
8 15
@@ -157,14 +164,17 @@ class Article &lt; ActiveRecord::Base @@ -157,14 +164,17 @@ class Article &lt; ActiveRecord::Base
157 self.profile 164 self.profile
158 end 165 end
159 166
160 - def self.human_attribute_name(attrib, options = {}) 167 + def self.human_attribute_name_with_customization(attrib, options={})
161 case attrib.to_sym 168 case attrib.to_sym
162 when :name 169 when :name
163 _('Title') 170 _('Title')
164 else 171 else
165 - _(self.superclass.human_attribute_name(attrib)) 172 + _(self.human_attribute_name_without_customization(attrib))
166 end 173 end
167 end 174 end
  175 + class << self
  176 + alias_method_chain :human_attribute_name, :customization
  177 + end
168 178
169 def css_class_list 179 def css_class_list
170 [self.class.name.to_css_class] 180 [self.class.name.to_css_class]
@@ -282,13 +292,6 @@ class Article &lt; ActiveRecord::Base @@ -282,13 +292,6 @@ class Article &lt; ActiveRecord::Base
282 end 292 end
283 end 293 end
284 294
285 - def reported_version(options = {})  
286 - article = self  
287 - search_path = Rails.root.join('app', 'views', 'shared', 'reported_versions')  
288 - partial_path = File.join('shared', 'reported_versions', partial_for_class_in_view_path(article.class, search_path))  
289 - lambda { render_to_string(:partial => partial_path, :locals => {:article => article}) }  
290 - end  
291 -  
292 # returns the data of the article. Must be overriden in each subclass to 295 # returns the data of the article. Must be overriden in each subclass to
293 # provide the correct content for the article. 296 # provide the correct content for the article.
294 def data 297 def data
@@ -337,7 +340,7 @@ class Article &lt; ActiveRecord::Base @@ -337,7 +340,7 @@ class Article &lt; ActiveRecord::Base
337 def belongs_to_blog? 340 def belongs_to_blog?
338 self.parent and self.parent.blog? 341 self.parent and self.parent.blog?
339 end 342 end
340 - 343 +
341 def belongs_to_forum? 344 def belongs_to_forum?
342 self.parent and self.parent.forum? 345 self.parent and self.parent.forum?
343 end 346 end
@@ -449,6 +452,7 @@ class Article &lt; ActiveRecord::Base @@ -449,6 +452,7 @@ class Article &lt; ActiveRecord::Base
449 if self.parent && !self.parent.published? 452 if self.parent && !self.parent.published?
450 return false 453 return false
451 end 454 end
  455 +
452 true 456 true
453 else 457 else
454 false 458 false
@@ -480,14 +484,17 @@ class Article &lt; ActiveRecord::Base @@ -480,14 +484,17 @@ class Article &lt; ActiveRecord::Base
480 {:conditions => [" articles.published = ? OR 484 {:conditions => [" articles.published = ? OR
481 articles.last_changed_by_id = ? OR 485 articles.last_changed_by_id = ? OR
482 articles.profile_id = ? OR 486 articles.profile_id = ? OR
483 - ?",  
484 - true, user.id, user.id, user.has_permission?(:view_private_content, profile)] } 487 + ? OR articles.show_to_followers = ? AND ?",
  488 + true, user.id, user.id, user.has_permission?(:view_private_content, profile),
  489 + true, user.follows?(profile)]}
485 end 490 end
486 491
  492 +
487 def display_unpublished_article_to?(user) 493 def display_unpublished_article_to?(user)
488 user == author || allow_view_private_content?(user) || user == profile || 494 user == author || allow_view_private_content?(user) || user == profile ||
489 user.is_admin?(profile.environment) || user.is_admin?(profile) || 495 user.is_admin?(profile.environment) || user.is_admin?(profile) ||
490 - article_privacy_exceptions.include?(user) 496 + article_privacy_exceptions.include?(user) ||
  497 + (self.show_to_followers && user.follows?(profile))
491 end 498 end
492 499
493 def display_to?(user = nil) 500 def display_to?(user = nil)
app/models/block.rb
1 class Block < ActiveRecord::Base 1 class Block < ActiveRecord::Base
2 2
3 - attr_accessible :title, :display, :limit, :box_id, :posts_per_page, :visualization_format, :language, :display_user, :box 3 + attr_accessible :title, :display, :limit, :box_id, :posts_per_page, :visualization_format, :language, :display_user, :box, :fixed
4 4
5 # to be able to generate HTML 5 # to be able to generate HTML
6 include ActionView::Helpers::UrlHelper 6 include ActionView::Helpers::UrlHelper
@@ -64,7 +64,7 @@ class Block &lt; ActiveRecord::Base @@ -64,7 +64,7 @@ class Block &lt; ActiveRecord::Base
64 end 64 end
65 65
66 def display_to_user?(user) 66 def display_to_user?(user)
67 - display_user == 'all' || (user.nil? && display_user == 'not_logged') || (user && display_user == 'logged') 67 + display_user == 'all' || (user.nil? && display_user == 'not_logged') || (user && display_user == 'logged') || (user && display_user == 'followers' && user.follows?(owner))
68 end 68 end
69 69
70 def display_always(context) 70 def display_always(context)
@@ -75,7 +75,7 @@ class Block &lt; ActiveRecord::Base @@ -75,7 +75,7 @@ class Block &lt; ActiveRecord::Base
75 if context[:article] 75 if context[:article]
76 return context[:article] == owner.home_page 76 return context[:article] == owner.home_page
77 else 77 else
78 - return context[:request_path] == '/' 78 + return home_page_path?(context[:request_path])
79 end 79 end
80 end 80 end
81 81
@@ -83,7 +83,7 @@ class Block &lt; ActiveRecord::Base @@ -83,7 +83,7 @@ class Block &lt; ActiveRecord::Base
83 if context[:article] 83 if context[:article]
84 return context[:article] != owner.home_page 84 return context[:article] != owner.home_page
85 else 85 else
86 - return context[:request_path] != '/' + (owner.kind_of?(Profile) ? owner.identifier : '') 86 + return !home_page_path?(context[:request_path])
87 end 87 end
88 end 88 end
89 89
@@ -110,11 +110,14 @@ class Block &lt; ActiveRecord::Base @@ -110,11 +110,14 @@ class Block &lt; ActiveRecord::Base
110 # * <tt>'all'</tt>: the block is always displayed 110 # * <tt>'all'</tt>: the block is always displayed
111 settings_items :language, :type => :string, :default => 'all' 111 settings_items :language, :type => :string, :default => 'all'
112 112
  113 + # The block can be configured to be fixed. Only can be edited by environment admins
  114 + settings_items :fixed, :type => :boolean, :default => false
  115 +
113 # returns the description of the block, used when the user sees a list of 116 # returns the description of the block, used when the user sees a list of
114 # blocks to choose one to include in the design. 117 # blocks to choose one to include in the design.
115 # 118 #
116 # Must be redefined in subclasses to match the description of each block 119 # Must be redefined in subclasses to match the description of each block
117 - # type. 120 + # type.
118 def self.description 121 def self.description
119 '(dummy)' 122 '(dummy)'
120 end 123 end
@@ -124,13 +127,13 @@ class Block &lt; ActiveRecord::Base @@ -124,13 +127,13 @@ class Block &lt; ActiveRecord::Base
124 # This method can return several types of objects: 127 # This method can return several types of objects:
125 # 128 #
126 # * <tt>String</tt>: if the string starts with <tt>http://</tt> or <tt>https://</tt>, then it is assumed to be address of an IFRAME. Otherwise it's is used as regular HTML. 129 # * <tt>String</tt>: if the string starts with <tt>http://</tt> or <tt>https://</tt>, then it is assumed to be address of an IFRAME. Otherwise it's is used as regular HTML.
127 - # * <tt>Hash</tt>: the hash is used to build an URL that is used as the address for a IFRAME. 130 + # * <tt>Hash</tt>: the hash is used to build an URL that is used as the address for a IFRAME.
128 # * <tt>Proc</tt>: the Proc is evaluated in the scope of BoxesHelper. The 131 # * <tt>Proc</tt>: the Proc is evaluated in the scope of BoxesHelper. The
129 # block can then use <tt>render</tt>, <tt>link_to</tt>, etc. 132 # block can then use <tt>render</tt>, <tt>link_to</tt>, etc.
130 # 133 #
131 # The method can also return <tt>nil</tt>, which means "no content". 134 # The method can also return <tt>nil</tt>, which means "no content".
132 # 135 #
133 - # See BoxesHelper#extract_block_content for implementation details. 136 + # See BoxesHelper#extract_block_content for implementation details.
134 def content(args={}) 137 def content(args={})
135 "This is block number %d" % self.id 138 "This is block number %d" % self.id
136 end 139 end
@@ -192,7 +195,7 @@ class Block &lt; ActiveRecord::Base @@ -192,7 +195,7 @@ class Block &lt; ActiveRecord::Base
192 195
193 # Override in your subclasses. 196 # Override in your subclasses.
194 # Define which events and context should cause the block cache to expire 197 # Define which events and context should cause the block cache to expire
195 - # Possible events are: :article, :profile, :friendship, :category 198 + # Possible events are: :article, :profile, :friendship, :category, :role_assignment
196 # Possible contexts are: :profile, :environment 199 # Possible contexts are: :profile, :environment
197 def self.expire_on 200 def self.expire_on
198 { 201 {
@@ -221,6 +224,7 @@ class Block &lt; ActiveRecord::Base @@ -221,6 +224,7 @@ class Block &lt; ActiveRecord::Base
221 'all' => _('All users'), 224 'all' => _('All users'),
222 'logged' => _('Logged'), 225 'logged' => _('Logged'),
223 'not_logged' => _('Not logged'), 226 'not_logged' => _('Not logged'),
  227 + 'followers' => owner.class != Environment && owner.organization? ? _('Members') : _('Friends')
224 } 228 }
225 end 229 end
226 230
@@ -234,4 +238,26 @@ class Block &lt; ActiveRecord::Base @@ -234,4 +238,26 @@ class Block &lt; ActiveRecord::Base
234 duplicated_block 238 duplicated_block
235 end 239 end
236 240
  241 + def copy_from(block)
  242 + self.settings = block.settings
  243 + self.position = block.position
  244 + end
  245 +
  246 + private
  247 +
  248 + def home_page_path
  249 + home_page_url = Noosfero.root('/')
  250 +
  251 + if owner.kind_of?(Profile)
  252 + home_page_url += "profile/" if owner.home_page.nil?
  253 + home_page_url += owner.identifier
  254 + end
  255 +
  256 + return home_page_url
  257 + end
  258 +
  259 + def home_page_path? path
  260 + return path == home_page_path || path == (home_page_path + '/')
  261 + end
  262 +
237 end 263 end
app/models/blog.rb
@@ -53,7 +53,7 @@ class Blog &lt; Folder @@ -53,7 +53,7 @@ class Blog &lt; Folder
53 def prepare_external_feed 53 def prepare_external_feed
54 unless self.external_feed_data.nil? 54 unless self.external_feed_data.nil?
55 if self.external_feed(true) && self.external_feed.id == self.external_feed_data[:id].to_i 55 if self.external_feed(true) && self.external_feed.id == self.external_feed_data[:id].to_i
56 - self.external_feed.attributes = self.external_feed_data 56 + self.external_feed.attributes = self.external_feed_data.except(:id)
57 else 57 else
58 self.build_external_feed(self.external_feed_data, :without_protection => true) 58 self.build_external_feed(self.external_feed_data, :without_protection => true)
59 end 59 end
app/models/change_password.rb
@@ -2,16 +2,19 @@ class ChangePassword &lt; Task @@ -2,16 +2,19 @@ class ChangePassword &lt; Task
2 2
3 attr_accessor :password, :password_confirmation 3 attr_accessor :password, :password_confirmation
4 4
5 - def self.human_attribute_name(attrib, options = {}) 5 + def self.human_attribute_name_with_customization(attrib, options={})
6 case attrib.to_sym 6 case attrib.to_sym
7 when :password 7 when :password
8 _('Password') 8 _('Password')
9 when :password_confirmation 9 when :password_confirmation
10 _('Password Confirmation') 10 _('Password Confirmation')
11 else 11 else
12 - _(self.superclass.human_attribute_name(attrib)) 12 + _(self.human_attribute_name_without_customization(attrib))
13 end 13 end
14 end 14 end
  15 + class << self
  16 + alias_method_chain :human_attribute_name, :customization
  17 + end
15 18
16 validates_presence_of :requestor 19 validates_presence_of :requestor
17 20
app/models/community.rb
@@ -50,16 +50,6 @@ class Community &lt; Organization @@ -50,16 +50,6 @@ class Community &lt; Organization
50 super + FIELDS 50 super + FIELDS
51 end 51 end
52 52
53 - validate :presence_of_required_fieds  
54 -  
55 - def presence_of_required_fieds  
56 - self.required_fields.each do |field|  
57 - if self.send(field).blank?  
58 - self.errors.add_on_blank(field)  
59 - end  
60 - end  
61 - end  
62 -  
63 def active_fields 53 def active_fields
64 environment ? environment.active_community_fields : [] 54 environment ? environment.active_community_fields : []
65 end 55 end
@@ -78,7 +68,7 @@ class Community &lt; Organization @@ -78,7 +68,7 @@ class Community &lt; Organization
78 end 68 end
79 69
80 def default_template 70 def default_template
81 - environment.community_template 71 + environment.community_default_template
82 end 72 end
83 73
84 def news(limit = 30, highlight = false) 74 def news(limit = 30, highlight = false)
app/models/domain.rb
@@ -92,4 +92,11 @@ class Domain &lt; ActiveRecord::Base @@ -92,4 +92,11 @@ class Domain &lt; ActiveRecord::Base
92 @hosting = {} 92 @hosting = {}
93 end 93 end
94 94
  95 + # Detects a domain's custom text domain chain if available based on a domain
  96 + # served on multitenancy configuration or a registered domain.
  97 + def self.custom_locale(domainname)
  98 + domain = Noosfero::MultiTenancy.mapping[domainname] || domainname[/(.*?)\./,1]
  99 + FastGettext.translation_repositories.keys.include?(domain) ? domain : FastGettext.default_text_domain
  100 + end
  101 +
95 end 102 end
app/models/enterprise.rb
@@ -59,16 +59,6 @@ class Enterprise &lt; Organization @@ -59,16 +59,6 @@ class Enterprise &lt; Organization
59 super + FIELDS 59 super + FIELDS
60 end 60 end
61 61
62 - validate :presence_of_required_fieds  
63 -  
64 - def presence_of_required_fieds  
65 - self.required_fields.each do |field|  
66 - if self.send(field).blank?  
67 - self.errors.add_on_blank(field)  
68 - end  
69 - end  
70 - end  
71 -  
72 def active_fields 62 def active_fields
73 environment ? environment.active_enterprise_fields : [] 63 environment ? environment.active_enterprise_fields : []
74 end 64 end
@@ -107,7 +97,12 @@ class Enterprise &lt; Organization @@ -107,7 +97,12 @@ class Enterprise &lt; Organization
107 self.tasks.where(:type => 'EnterpriseActivation').first 97 self.tasks.where(:type => 'EnterpriseActivation').first
108 end 98 end
109 99
110 - def enable(owner) 100 + def enable(owner = nil)
  101 + if owner.nil?
  102 + self.visible = true
  103 + return self.save
  104 + end
  105 +
111 return if enabled 106 return if enabled
112 # must be set first for the following to work 107 # must be set first for the following to work
113 self.enabled = true 108 self.enabled = true
@@ -169,7 +164,7 @@ class Enterprise &lt; Organization @@ -169,7 +164,7 @@ class Enterprise &lt; Organization
169 end 164 end
170 165
171 def default_template 166 def default_template
172 - environment.enterprise_template 167 + environment.enterprise_default_template
173 end 168 end
174 169
175 def template_with_inactive_enterprise 170 def template_with_inactive_enterprise
app/models/environment.rb
@@ -283,6 +283,7 @@ class Environment &lt; ActiveRecord::Base @@ -283,6 +283,7 @@ class Environment &lt; ActiveRecord::Base
283 www.flickr.com 283 www.flickr.com
284 www.gmodules.com 284 www.gmodules.com
285 www.youtube.com 285 www.youtube.com
  286 + openstreetmap.org
286 ] + ('a' .. 'z').map{|i| "#{i}.yimg.com"} 287 ] + ('a' .. 'z').map{|i| "#{i}.yimg.com"}
287 288
288 settings_items :enabled_plugins, :type => Array, :default => Noosfero::Plugin.available_plugin_names 289 settings_items :enabled_plugins, :type => Array, :default => Noosfero::Plugin.available_plugin_names
@@ -656,10 +657,11 @@ class Environment &lt; ActiveRecord::Base @@ -656,10 +657,11 @@ class Environment &lt; ActiveRecord::Base
656 { :controller => 'admin_panel', :action => 'index' } 657 { :controller => 'admin_panel', :action => 'index' }
657 end 658 end
658 659
659 - def top_url  
660 - url = 'http://' 660 + def top_url(scheme = 'http')
  661 + url = scheme + '://'
661 url << (Noosfero.url_options.key?(:host) ? Noosfero.url_options[:host] : default_hostname) 662 url << (Noosfero.url_options.key?(:host) ? Noosfero.url_options[:host] : default_hostname)
662 url << ':' << Noosfero.url_options[:port].to_s if Noosfero.url_options.key?(:port) 663 url << ':' << Noosfero.url_options[:port].to_s if Noosfero.url_options.key?(:port)
  664 + url << Noosfero.root('')
663 url 665 url
664 end 666 end
665 667
@@ -727,31 +729,50 @@ class Environment &lt; ActiveRecord::Base @@ -727,31 +729,50 @@ class Environment &lt; ActiveRecord::Base
727 ] 729 ]
728 end 730 end
729 731
730 - def community_template 732 + def is_default_template?(template)
  733 + is_default = template == community_default_template
  734 + is_default = is_default || template == person_default_template
  735 + is_default = is_default || template == enterprise_default_template
  736 + is_default
  737 + end
  738 +
  739 + def community_templates
  740 + self.communities.templates
  741 + end
  742 +
  743 + def community_default_template
731 template = Community.find_by_id settings[:community_template_id] 744 template = Community.find_by_id settings[:community_template_id]
732 - template if template && template.is_template 745 + template if template && template.is_template?
  746 + end
  747 +
  748 + def community_default_template=(value)
  749 + settings[:community_template_id] = value.kind_of?(Community) ? value.id : value
733 end 750 end
734 751
735 - def community_template=(value)  
736 - settings[:community_template_id] = value.id 752 + def person_templates
  753 + self.people.templates
737 end 754 end
738 755
739 - def person_template 756 + def person_default_template
740 template = Person.find_by_id settings[:person_template_id] 757 template = Person.find_by_id settings[:person_template_id]
741 - template if template && template.is_template 758 + template if template && template.is_template?
  759 + end
  760 +
  761 + def person_default_template=(value)
  762 + settings[:person_template_id] = value.kind_of?(Person) ? value.id : value
742 end 763 end
743 764
744 - def person_template=(value)  
745 - settings[:person_template_id] = value.id 765 + def enterprise_templates
  766 + self.enterprises.templates
746 end 767 end
747 768
748 - def enterprise_template 769 + def enterprise_default_template
749 template = Enterprise.find_by_id settings[:enterprise_template_id] 770 template = Enterprise.find_by_id settings[:enterprise_template_id]
750 - template if template && template.is_template 771 + template if template && template.is_template?
751 end 772 end
752 773
753 - def enterprise_template=(value)  
754 - settings[:enterprise_template_id] = value.id 774 + def enterprise_default_template=(value)
  775 + settings[:enterprise_template_id] = value.kind_of?(Enterprise) ? value.id : value
755 end 776 end
756 777
757 def inactive_enterprise_template 778 def inactive_enterprise_template
@@ -804,7 +825,7 @@ class Environment &lt; ActiveRecord::Base @@ -804,7 +825,7 @@ class Environment &lt; ActiveRecord::Base
804 end 825 end
805 826
806 def notification_emails 827 def notification_emails
807 - [noreply_email.blank? ? nil : noreply_email].compact + admins.map(&:email) 828 + [contact_email].select(&:present?) + admins.map(&:email)
808 end 829 end
809 830
810 after_create :create_templates 831 after_create :create_templates
@@ -849,10 +870,10 @@ class Environment &lt; ActiveRecord::Base @@ -849,10 +870,10 @@ class Environment &lt; ActiveRecord::Base
849 person_template.visible = false 870 person_template.visible = false
850 person_template.save! 871 person_template.save!
851 872
852 - self.enterprise_template = enterprise_template 873 + self.enterprise_default_template = enterprise_template
853 self.inactive_enterprise_template = inactive_enterprise_template 874 self.inactive_enterprise_template = inactive_enterprise_template
854 - self.community_template = community_template  
855 - self.person_template = person_template 875 + self.community_default_template = community_template
  876 + self.person_default_template = person_template
856 self.save! 877 self.save!
857 end 878 end
858 879
@@ -916,6 +937,10 @@ class Environment &lt; ActiveRecord::Base @@ -916,6 +937,10 @@ class Environment &lt; ActiveRecord::Base
916 locales_list 937 locales_list
917 end 938 end
918 939
  940 + def has_license?
  941 + self.licenses.any?
  942 + end
  943 +
919 private 944 private
920 945
921 def default_language_available 946 def default_language_available
app/models/event.rb
@@ -19,7 +19,7 @@ class Event &lt; Article @@ -19,7 +19,7 @@ class Event &lt; Article
19 maybe_add_http(self.setting[:link]) 19 maybe_add_http(self.setting[:link])
20 end 20 end
21 21
22 - xss_terminate :only => [ :body, :link, :address ], :with => 'white_list', :on => 'validation' 22 + xss_terminate :only => [ :name, :body, :link, :address ], :with => 'white_list', :on => 'validation'
23 23
24 def initialize(*args) 24 def initialize(*args)
25 super(*args) 25 super(*args)
app/models/external_feed.rb
@@ -10,9 +10,10 @@ class ExternalFeed &lt; ActiveRecord::Base @@ -10,9 +10,10 @@ class ExternalFeed &lt; ActiveRecord::Base
10 { :conditions => ['(fetched_at is NULL) OR (fetched_at < ?)', Time.now - FeedUpdater.update_interval] } 10 { :conditions => ['(fetched_at is NULL) OR (fetched_at < ?)', Time.now - FeedUpdater.update_interval] }
11 } 11 }
12 12
13 - attr_accessible :address, :enabled 13 + attr_accessible :address, :enabled, :only_once
14 14
15 def add_item(title, link, date, content) 15 def add_item(title, link, date, content)
  16 + return if content.blank?
16 doc = Hpricot(content) 17 doc = Hpricot(content)
17 doc.search('*').each do |p| 18 doc.search('*').each do |p|
18 if p.instance_of? Hpricot::Elem 19 if p.instance_of? Hpricot::Elem
@@ -30,6 +31,7 @@ class ExternalFeed &lt; ActiveRecord::Base @@ -30,6 +31,7 @@ class ExternalFeed &lt; ActiveRecord::Base
30 article.source = link 31 article.source = link
31 article.profile = blog.profile 32 article.profile = blog.profile
32 article.parent = blog 33 article.parent = blog
  34 + article.author_name = self.feed_title
33 unless blog.children.exists?(:slug => article.slug) 35 unless blog.children.exists?(:slug => article.slug)
34 article.save! 36 article.save!
35 article.delay.create_activity 37 article.delay.create_activity
app/models/feed_reader_block.rb
@@ -85,8 +85,4 @@ class FeedReaderBlock &lt; Block @@ -85,8 +85,4 @@ class FeedReaderBlock &lt; Block
85 block_title(title) + formatted_feed_content 85 block_title(title) + formatted_feed_content
86 end 86 end
87 87
88 - def editable?  
89 - true  
90 - end  
91 -  
92 end 88 end
app/models/folder.rb
@@ -12,7 +12,7 @@ class Folder &lt; Article @@ -12,7 +12,7 @@ class Folder &lt; Article
12 12
13 acts_as_having_settings :field => :setting 13 acts_as_having_settings :field => :setting
14 14
15 - xss_terminate :only => [ :body ], :with => 'white_list', :on => 'validation' 15 + xss_terminate :only => [ :name, :body ], :with => 'white_list', :on => 'validation'
16 16
17 include WhiteListFilter 17 include WhiteListFilter
18 filter_iframes :body 18 filter_iframes :body
app/models/invitation.rb
@@ -65,18 +65,16 @@ class Invitation &lt; Task @@ -65,18 +65,16 @@ class Invitation &lt; Task
65 65
66 task_args = if user.nil? 66 task_args = if user.nil?
67 {:person => person, :friend_name => friend_name, :friend_email => friend_email, :message => message} 67 {:person => person, :friend_name => friend_name, :friend_email => friend_email, :message => message}
68 - elsif !user.person.is_a_friend?(person) 68 + else
69 {:person => person, :target => user.person} 69 {:person => person, :target => user.person}
70 end 70 end
71 71
72 - if !task_args.nil?  
73 - if profile.person?  
74 - InviteFriend.create(task_args)  
75 - elsif profile.community?  
76 - InviteMember.create(task_args.merge(:community_id => profile.id))  
77 - else  
78 - raise NotImplementedError, 'Don\'t know how to invite people to a %s' % profile.class.to_s  
79 - end 72 + if profile.person?
  73 + InviteFriend.create(task_args) if user.nil? || !user.person.is_a_friend?(person)
  74 + elsif profile.community?
  75 + InviteMember.create(task_args.merge(:community_id => profile.id)) if user.nil? || !user.person.is_member_of?(profile)
  76 + else
  77 + raise NotImplementedError, 'Don\'t know how to invite people to a %s' % profile.class.to_s
80 end 78 end
81 end 79 end
82 end 80 end
app/models/link_list_block.rb
@@ -78,16 +78,17 @@ class LinkListBlock &lt; Block @@ -78,16 +78,17 @@ class LinkListBlock &lt; Block
78 address 78 address
79 end 79 end
80 if add !~ /^[a-z]+:\/\// && add !~ /^\// 80 if add !~ /^[a-z]+:\/\// && add !~ /^\//
81 - 'http://' + add 81 + '//' + add
82 else 82 else
  83 + if root = Noosfero.root
  84 + if !add.starts_with?(root)
  85 + add = root + add
  86 + end
  87 + end
83 add 88 add
84 end 89 end
85 end 90 end
86 91
87 - def editable?  
88 - true  
89 - end  
90 -  
91 def icons_options 92 def icons_options
92 ICONS.map do |i| 93 ICONS.map do |i|
93 "<span title=\"#{i[1]}\" class=\"icon-#{i[0]}\" onclick=\"changeIcon(this, '#{i[0]}')\"></span>".html_safe 94 "<span title=\"#{i[1]}\" class=\"icon-#{i[0]}\" onclick=\"changeIcon(this, '#{i[0]}')\"></span>".html_safe
@@ -100,4 +101,5 @@ class LinkListBlock &lt; Block @@ -100,4 +101,5 @@ class LinkListBlock &lt; Block
100 sanitizer = HTML::WhiteListSanitizer.new 101 sanitizer = HTML::WhiteListSanitizer.new
101 sanitizer.sanitize(text) 102 sanitizer.sanitize(text)
102 end 103 end
  104 +
103 end 105 end
app/models/main_block.rb
@@ -16,10 +16,6 @@ class MainBlock &lt; Block @@ -16,10 +16,6 @@ class MainBlock &lt; Block
16 true 16 true
17 end 17 end
18 18
19 - def editable?  
20 - true  
21 - end  
22 -  
23 def cacheable? 19 def cacheable?
24 false 20 false
25 end 21 end
app/models/organization.rb
@@ -30,6 +30,16 @@ class Organization &lt; Profile @@ -30,6 +30,16 @@ class Organization &lt; Profile
30 30
31 scope :more_popular, :order => 'members_count DESC' 31 scope :more_popular, :order => 'members_count DESC'
32 32
  33 + validate :presence_of_required_fieds, :unless => :is_template
  34 +
  35 + def presence_of_required_fieds
  36 + self.required_fields.each do |field|
  37 + if self.send(field).blank?
  38 + self.errors.add_on_blank(field)
  39 + end
  40 + end
  41 + end
  42 +
33 def validation_methodology 43 def validation_methodology
34 self.validation_info ? self.validation_info.validation_methodology : nil 44 self.validation_info ? self.validation_info.validation_methodology : nil
35 end 45 end
@@ -135,7 +145,11 @@ class Organization &lt; Profile @@ -135,7 +145,11 @@ class Organization &lt; Profile
135 end 145 end
136 146
137 def notification_emails 147 def notification_emails
138 - [contact_email.blank? ? nil : contact_email].compact + admins.map(&:email) 148 + emails = [contact_email].select(&:present?) + admins.map(&:email)
  149 + if emails.empty?
  150 + emails << environment.contact_email
  151 + end
  152 + emails
139 end 153 end
140 154
141 def already_request_membership?(person) 155 def already_request_membership?(person)
app/models/person.rb
@@ -21,6 +21,12 @@ class Person &lt; Profile @@ -21,6 +21,12 @@ class Person &lt; Profile
21 { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => [conditions] } 21 { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => [conditions] }
22 } 22 }
23 23
  24 + scope :by_role, lambda { |roles|
  25 + roles = [roles] unless roles.kind_of?(Array)
  26 + { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => ['role_assignments.role_id IN (?)',
  27 +roles] }
  28 + }
  29 +
24 def has_permission_with_plugins?(permission, profile) 30 def has_permission_with_plugins?(permission, profile)
25 permissions = [has_permission_without_plugins?(permission, profile)] 31 permissions = [has_permission_without_plugins?(permission, profile)]
26 permissions += plugins.map do |plugin| 32 permissions += plugins.map do |plugin|
@@ -74,6 +80,10 @@ class Person &lt; Profile @@ -74,6 +80,10 @@ class Person &lt; Profile
74 80
75 belongs_to :user, :dependent => :delete 81 belongs_to :user, :dependent => :delete
76 82
  83 + def can_change_homepage?
  84 + !environment.enabled?('cant_change_homepage') || is_admin?
  85 + end
  86 +
77 def can_control_scrap?(scrap) 87 def can_control_scrap?(scrap)
78 begin 88 begin
79 !self.scraps(scrap).nil? 89 !self.scraps(scrap).nil?
@@ -161,7 +171,7 @@ class Person &lt; Profile @@ -161,7 +171,7 @@ class Person &lt; Profile
161 FIELDS 171 FIELDS
162 end 172 end
163 173
164 - validate :presence_of_required_fields 174 + validate :presence_of_required_fields, :unless => :is_template
165 175
166 def presence_of_required_fields 176 def presence_of_required_fields
167 self.required_fields.each do |field| 177 self.required_fields.each do |field|
@@ -300,7 +310,7 @@ class Person &lt; Profile @@ -300,7 +310,7 @@ class Person &lt; Profile
300 end 310 end
301 311
302 def default_template 312 def default_template
303 - environment.person_template 313 + environment.person_default_template
304 end 314 end
305 315
306 def apply_type_specific_template(template) 316 def apply_type_specific_template(template)
app/models/person_notifier.rb
@@ -67,7 +67,7 @@ class PersonNotifier @@ -67,7 +67,7 @@ class PersonNotifier
67 67
68 class Mailer < ActionMailer::Base 68 class Mailer < ActionMailer::Base
69 69
70 - add_template_helper(PersonNotifierHelper) 70 + add_template_helper(ApplicationHelper)
71 71
72 def session 72 def session
73 {:theme => nil} 73 {:theme => nil}
app/models/product.rb
@@ -11,7 +11,7 @@ class Product &lt; ActiveRecord::Base @@ -11,7 +11,7 @@ class Product &lt; ActiveRecord::Base
11 11
12 SEARCH_DISPLAYS = %w[map full] 12 SEARCH_DISPLAYS = %w[map full]
13 13
14 - attr_accessible :name, :product_category, :highlighted, :price, :enterprise, :image_builder, :description, :available, :qualifiers, :unit_id, :discount, :inputs 14 + attr_accessible :name, :product_category, :highlighted, :price, :enterprise, :image_builder, :description, :available, :qualifiers, :unit_id, :discount, :inputs, :qualifiers_list
15 15
16 def self.default_search_display 16 def self.default_search_display
17 'full' 17 'full'
app/models/profile.rb
@@ -125,7 +125,7 @@ class Profile &lt; ActiveRecord::Base @@ -125,7 +125,7 @@ class Profile &lt; ActiveRecord::Base
125 end 125 end
126 126
127 def members_by_name 127 def members_by_name
128 - members.order(:name) 128 + members.order('profiles.name')
129 end 129 end
130 130
131 class << self 131 class << self
@@ -136,8 +136,8 @@ class Profile &lt; ActiveRecord::Base @@ -136,8 +136,8 @@ class Profile &lt; ActiveRecord::Base
136 alias_method_chain :count, :distinct 136 alias_method_chain :count, :distinct
137 end 137 end
138 138
139 - def members_by_role(role)  
140 - Person.members_of(self).all(:conditions => ['role_assignments.role_id = ?', role.id]) 139 + def members_by_role(roles)
  140 + Person.members_of(self).by_role(roles)
141 end 141 end
142 142
143 acts_as_having_boxes 143 acts_as_having_boxes
@@ -149,7 +149,9 @@ class Profile &lt; ActiveRecord::Base @@ -149,7 +149,9 @@ class Profile &lt; ActiveRecord::Base
149 end 149 end
150 150
151 scope :visible, :conditions => { :visible => true } 151 scope :visible, :conditions => { :visible => true }
  152 + scope :disabled, :conditions => { :visible => false }
152 scope :public, :conditions => { :visible => true, :public_profile => true } 153 scope :public, :conditions => { :visible => true, :public_profile => true }
  154 + scope :enabled, :conditions => { :enabled => true }
153 155
154 # Subclasses must override this method 156 # Subclasses must override this method
155 scope :more_popular 157 scope :more_popular
@@ -374,16 +376,17 @@ class Profile &lt; ActiveRecord::Base @@ -374,16 +376,17 @@ class Profile &lt; ActiveRecord::Base
374 end 376 end
375 377
376 def copy_blocks_from(profile) 378 def copy_blocks_from(profile)
  379 + template_boxes = profile.boxes.select{|box| box.position}
377 self.boxes.destroy_all 380 self.boxes.destroy_all
378 - profile.boxes.each do |box|  
379 - new_box = Box.new 381 + self.boxes = template_boxes.size.times.map { Box.new }
  382 +
  383 + template_boxes.each_with_index do |box, i|
  384 + new_box = self.boxes[i]
380 new_box.position = box.position 385 new_box.position = box.position
381 - self.boxes << new_box  
382 box.blocks.each do |block| 386 box.blocks.each do |block|
383 new_block = block.class.new(:title => block[:title]) 387 new_block = block.class.new(:title => block[:title])
384 - new_block.settings = block.settings  
385 - new_block.position = block.position  
386 - self.boxes[-1].blocks << new_block 388 + new_block.copy_from(block)
  389 + new_box.blocks << new_block
387 end 390 end
388 end 391 end
389 end 392 end
@@ -418,7 +421,7 @@ class Profile &lt; ActiveRecord::Base @@ -418,7 +421,7 @@ class Profile &lt; ActiveRecord::Base
418 end 421 end
419 422
420 xss_terminate :only => [ :name, :nickname, :address, :contact_phone, :description ], :on => 'validation' 423 xss_terminate :only => [ :name, :nickname, :address, :contact_phone, :description ], :on => 'validation'
421 - xss_terminate :only => [ :custom_footer, :custom_header ], :with => 'white_list', :on => 'validation' 424 + xss_terminate :only => [ :custom_footer, :custom_header ], :with => 'white_list'
422 425
423 include WhiteListFilter 426 include WhiteListFilter
424 filter_iframes :custom_header, :custom_footer 427 filter_iframes :custom_header, :custom_footer
@@ -802,7 +805,7 @@ private :generate_url, :url_options @@ -802,7 +805,7 @@ private :generate_url, :url_options
802 end 805 end
803 806
804 include Noosfero::Plugin::HotSpot 807 include Noosfero::Plugin::HotSpot
805 - 808 +
806 def folder_types 809 def folder_types
807 types = Article.folder_types 810 types = Article.folder_types
808 plugins.dispatch(:content_types).each {|type| 811 plugins.dispatch(:content_types).each {|type|
@@ -926,6 +929,13 @@ private :generate_url, :url_options @@ -926,6 +929,13 @@ private :generate_url, :url_options
926 end 929 end
927 930
928 def disable 931 def disable
  932 + self.visible = false
  933 + self.save
  934 + end
  935 +
  936 + def enable
  937 + self.visible = true
  938 + self.save
929 end 939 end
930 940
931 def control_panel_settings_button 941 def control_panel_settings_button
app/models/profile_image_block.rb
@@ -23,10 +23,6 @@ class ProfileImageBlock &lt; Block @@ -23,10 +23,6 @@ class ProfileImageBlock &lt; Block
23 end 23 end
24 end 24 end
25 25
26 - def editable?  
27 - true  
28 - end  
29 -  
30 def cacheable? 26 def cacheable?
31 false 27 false
32 end 28 end
app/models/profile_info_block.rb
@@ -15,10 +15,6 @@ class ProfileInfoBlock &lt; Block @@ -15,10 +15,6 @@ class ProfileInfoBlock &lt; Block
15 end 15 end
16 end 16 end
17 17
18 - def editable?  
19 - false  
20 - end  
21 -  
22 def cacheable? 18 def cacheable?
23 false 19 false
24 end 20 end
app/models/profile_search_block.rb
@@ -11,8 +11,4 @@ class ProfileSearchBlock &lt; Block @@ -11,8 +11,4 @@ class ProfileSearchBlock &lt; Block
11 end 11 end
12 end 12 end
13 13
14 - def editable?  
15 - true  
16 - end  
17 -  
18 end 14 end
app/models/task.rb
@@ -285,8 +285,9 @@ class Task &lt; ActiveRecord::Base @@ -285,8 +285,9 @@ class Task &lt; ActiveRecord::Base
285 # If 285 # If
286 def send_notification(action) 286 def send_notification(action)
287 if sends_email? 287 if sends_email?
288 - if self.requestor  
289 - TaskMailer.generic_message("task_#{action}", self) 288 + if self.requestor && !self.requestor.notification_emails.empty?
  289 + message = TaskMailer.generic_message("task_#{action}", self)
  290 + message.deliver if message
290 end 291 end
291 end 292 end
292 end 293 end
app/models/user.rb
@@ -16,15 +16,18 @@ class User &lt; ActiveRecord::Base @@ -16,15 +16,18 @@ class User &lt; ActiveRecord::Base
16 end 16 end
17 17
18 # FIXME ugly workaround 18 # FIXME ugly workaround
19 - def self.human_attribute_name(attrib, options={}) 19 + def self.human_attribute_name_with_customization(attrib, options={})
20 case attrib.to_sym 20 case attrib.to_sym
21 when :login 21 when :login
22 return [_('Username'), _('Email')].join(' / ') 22 return [_('Username'), _('Email')].join(' / ')
23 when :email 23 when :email
24 return _('e-Mail') 24 return _('e-Mail')
25 - else _(self.superclass.human_attribute_name(attrib)) 25 + else _(self.human_attribute_name_without_customization(attrib))
26 end 26 end
27 end 27 end
  28 + class << self
  29 + alias_method_chain :human_attribute_name, :customization
  30 + end
28 31
29 before_create do |user| 32 before_create do |user|
30 if user.environment.nil? 33 if user.environment.nil?
@@ -198,6 +201,10 @@ class User &lt; ActiveRecord::Base @@ -198,6 +201,10 @@ class User &lt; ActiveRecord::Base
198 Digest::MD5.hexdigest(password) 201 Digest::MD5.hexdigest(password)
199 end 202 end
200 203
  204 + add_encryption_method :salted_md5 do |password, salt|
  205 + Digest::MD5.hexdigest(password+salt)
  206 + end
  207 +
201 add_encryption_method :clear do |password, salt| 208 add_encryption_method :clear do |password, salt|
202 password 209 password
203 end 210 end
@@ -347,6 +354,7 @@ class User &lt; ActiveRecord::Base @@ -347,6 +354,7 @@ class User &lt; ActiveRecord::Base
347 end 354 end
348 355
349 def delay_activation_check 356 def delay_activation_check
  357 + return if person.is_template?
350 Delayed::Job.enqueue(UserActivationJob.new(self.id), {:priority => 0, :run_at => 72.hours.from_now}) 358 Delayed::Job.enqueue(UserActivationJob.new(self.id), {:priority => 0, :run_at => 72.hours.from_now})
351 end 359 end
352 end 360 end
app/sweepers/role_assignment_sweeper.rb
@@ -13,20 +13,22 @@ class RoleAssignmentSweeper &lt; ActiveRecord::Observer @@ -13,20 +13,22 @@ class RoleAssignmentSweeper &lt; ActiveRecord::Observer
13 protected 13 protected
14 14
15 def expire_caches(role_assignment) 15 def expire_caches(role_assignment)
16 - expire_cache(role_assignment.accessor)  
17 - expire_cache(role_assignment.resource) if role_assignment.resource.respond_to?(:cache_keys) 16 + expire_cache(role_assignment.accessor) if role_assignment.accessor.kind_of?(Profile)
  17 + expire_cache(role_assignment.resource) if role_assignment.resource.kind_of?(Profile)
18 end 18 end
19 19
20 def expire_cache(profile) 20 def expire_cache(profile)
21 per_page = Noosfero::Constants::PROFILE_PER_PAGE 21 per_page = Noosfero::Constants::PROFILE_PER_PAGE
22 - profile.cache_keys(:per_page => per_page).each { |ck|  
23 - expire_timeout_fragment(ck)  
24 - } 22 +
  23 + profile.cache_keys(:per_page => per_page).each { |ck| expire_timeout_fragment(ck) }
  24 + expire_timeout_fragment(profile.members_cache_key(:per_page => per_page))
25 25
26 profile.blocks_to_expire_cache.each { |block| 26 profile.blocks_to_expire_cache.each { |block|
27 blocks = profile.blocks.select{|b| b.kind_of?(block)} 27 blocks = profile.blocks.select{|b| b.kind_of?(block)}
28 BlockSweeper.expire_blocks(blocks) 28 BlockSweeper.expire_blocks(blocks)
29 } 29 }
  30 +
  31 + expire_blocks_cache(profile, [:role_assignment])
30 end 32 end
31 33
32 end 34 end
app/views/admin_panel/index.html.erb
@@ -20,6 +20,7 @@ @@ -20,6 +20,7 @@
20 <tr><td><%= link_to _('Users'), :controller => 'users' %></td></tr> 20 <tr><td><%= link_to _('Users'), :controller => 'users' %></td></tr>
21 <tr><td><%= link_to _('Profile templates'), :controller => 'templates' %></td></tr> 21 <tr><td><%= link_to _('Profile templates'), :controller => 'templates' %></td></tr>
22 <tr><td><%= link_to _('Fields'), :controller => 'features', :action => 'manage_fields' %></td></tr> 22 <tr><td><%= link_to _('Fields'), :controller => 'features', :action => 'manage_fields' %></td></tr>
  23 + <tr><td><%= link_to _('Manage organizations status'), :action => 'manage_organizations_status' %></td></tr>
23 </table> 24 </table>
24 25
25 26
app/views/admin_panel/manage_organizations_status.html.erb 0 → 100644
@@ -0,0 +1,69 @@ @@ -0,0 +1,69 @@
  1 +<h1><%= _('Manage organizations') %></h1>
  2 +
  3 +<%= form_tag( { :action => 'manage_organizations_status' }, :method => 'get', :class => 'users-search' ) do %>
  4 +
  5 + <div class="search-field">
  6 + <span class="formfield">
  7 + <%= text_field_tag 'q', @q, :title => _("Find profiles"), :style=>"width:85%" %>
  8 + </span>
  9 +
  10 + <%= submit_button(:search, _('Search')) %>
  11 + </div>
  12 +
  13 + <div class="environment-users-results-header">
  14 + <div id='environment-users-filter-title'><%= @title %></div>
  15 +
  16 + <div id="environment-users-filter-filter">
  17 + <strong><%= _("Filter by: ") %></strong>
  18 +
  19 + <select id="profile_filter_select">
  20 + <%= options_for_select([['Any', 'any'],["Disabled profiles", "disabled"], ["Enabled profiles", "enabled"]], @filter) %>
  21 + </select>
  22 + </div>
  23 + <div style="clear: both"></div>
  24 + </div>
  25 +
  26 + <table>
  27 + <colgroup>
  28 + <col width="80%">
  29 + <col width="20%">
  30 + </colgroup>
  31 +
  32 + <tr>
  33 + <th><%= _('Member') %></th>
  34 + <th><%= _('Actions') %></th>
  35 + </tr>
  36 +
  37 + <% @collection.each do |p| %>
  38 + <tr title="<%= p.name %>">
  39 + <td><%= link_to_profile p.short_name, p.identifier, :title => p.name %> </td>
  40 +
  41 + <td class='actions'>
  42 + <div class="members-buttons-cell">
  43 + <% if p.visible %>
  44 + <%= button_without_text :'deactivate-user', _('Deactivate'), {:controller => "profile_editor", :action => 'deactivate_profile', :profile => p.identifier, :id => p.id}, :confirm => _("Do you want to deactivate this profile ?") %>
  45 + <% else %>
  46 + <%= button_without_text :'activate-user', _('Activate'), {:controller => "profile_editor", :action => 'activate_profile', :profile => p.identifier, :id => p.id}, :confirm => _("Do you want to activate this profile ?") %>
  47 + <% end %>
  48 + <%= button_without_text :'delete', _('Remove'), {:controller => "profile_editor", :action => 'destroy_profile', :profile => p.identifier, :id => p.id, :return_to => "/admin/admin_panel/manage_organizations_status"}, :method => :post, :confirm => _("Do you want to deactivate this profile ?") %>
  49 + </div>
  50 + </td>
  51 + </tr>
  52 + <% end %>
  53 + </table>
  54 +
  55 +<% end %>
  56 +
  57 +<%= pagination_links @collection, {:param_name => 'npage', :page_links => true} %>
  58 +
  59 +<% button_bar do %>
  60 + <%= button :back, _('Back'), :controller => 'admin_panel' %>
  61 +<% end %>
  62 +
  63 +<script type="text/javascript">
  64 + jQuery(document).ready(function(){
  65 + jQuery("#profile_filter_select").change(function(){
  66 + document.location.href = '/admin/admin_panel/manage_organizations_status?filter='+this.value;
  67 + });
  68 + });
  69 +</script>
0 \ No newline at end of file 70 \ No newline at end of file
app/views/box_organizer/edit.html.erb
@@ -5,6 +5,12 @@ @@ -5,6 +5,12 @@
5 5
6 <%= labelled_form_field(_('Custom title for this block: '), text_field(:block, :title, :maxlength => 20)) %> 6 <%= labelled_form_field(_('Custom title for this block: '), text_field(:block, :title, :maxlength => 20)) %>
7 7
  8 + <% if environment.admins.include?(user) %>
  9 + <div class="fixed_block">
  10 + <%= labelled_check_box(_("Fixed"), "block[fixed]", value = "1", checked = @block.fixed) %>
  11 + </div>
  12 + <% end %>
  13 +
8 <%= render :partial => partial_for_class(@block.class) %> 14 <%= render :partial => partial_for_class(@block.class) %>
9 15
10 <div class="display"> 16 <div class="display">
app/views/catalog/index.html.erb
@@ -14,8 +14,8 @@ @@ -14,8 +14,8 @@
14 14
15 <ul id="product-list"> 15 <ul id="product-list">
16 <% @products.each do |product| %> 16 <% @products.each do |product| %>
17 - <% extra_content = @plugins.dispatch(:catalog_item_extras, product).collect { |content| instance_eval(&content) } %>  
18 - <% extra_content_list = @plugins.dispatch(:catalog_list_item_extras, product).collect { |content| instance_eval(&content) } %> 17 + <% extra_content = @plugins.dispatch(:catalog_item_extras, product).collect { |content| instance_exec(&content) } %>
  18 + <% extra_content_list = @plugins.dispatch(:catalog_list_item_extras, product).collect { |content| instance_exec(&content) } %>
19 19
20 <% status = [] %> 20 <% status = [] %>
21 <% status << 'not-available' if !product.available %> 21 <% status << 'not-available' if !product.available %>
app/views/cms/_general_fields.html.erb
1 <%= select_profile_folder(_('Parent folder:'), 'article[parent_id]', profile, @article.parent_id) %> 1 <%= select_profile_folder(_('Parent folder:'), 'article[parent_id]', profile, @article.parent_id) %>
2 -<%= labelled_form_field(_('License'), select(:article, :license_id, options_for_select_with_title([[_('None'), nil]] + profile.environment.licenses.map {|license| [license.name, license.id]}, @article.license ? @article.license.id : nil))) %> 2 +<% if profile.environment.has_license? %>
  3 + <%= labelled_form_field(_('License'), select(:article, :license_id, options_for_select_with_title([[_('None'), nil]] + profile.environment.licenses.map {|license| [license.name, license.id]}, @article.license ? @article.license.id : nil))) %>
  4 +<% end %>
app/views/cms/upload_files.html.erb
@@ -20,5 +20,10 @@ @@ -20,5 +20,10 @@
20 <h5><%= _('Uploading files to %s') % content_tag('code', @target) %></h5> 20 <h5><%= _('Uploading files to %s') % content_tag('code', @target) %></h5>
21 21
22 <%= form_for('uploaded_file', :url => { :action => 'upload_files' }, :html => {:multipart => true}) do |f| %> 22 <%= form_for('uploaded_file', :url => { :action => 'upload_files' }, :html => {:multipart => true}) do |f| %>
  23 +
  24 + <%= @plugins.dispatch(:upload_files_extra_fields, params[:parent_id]).collect { |content| instance_exec(&content) }.join("") %>
  25 +
23 <%= render :partial => 'upload_file_form', :locals => { :size => '45'} %> 26 <%= render :partial => 'upload_file_form', :locals => { :size => '45'} %>
24 -<% end %> 27 +
  28 +<% end %>
  29 +
app/views/cms/view.html.erb
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 <%= _('Content management') %> 2 <%= _('Content management') %>
3 </h1> 3 </h1>
4 4
5 -<% if !environment.enabled?('cant_change_homepage') && !remove_content_button(:home) %> 5 +<% if user.can_change_homepage? && !remove_content_button(:home) %>
6 <div class="cms-homepage"> 6 <div class="cms-homepage">
7 <%= _('Profile homepage:') %> 7 <%= _('Profile homepage:') %>
8 <% if profile.home_page %> 8 <% if profile.home_page %>
@@ -69,7 +69,7 @@ @@ -69,7 +69,7 @@
69 <%= expirable_button article, :edit, _('Edit'), {:action => 'edit', :id => article.id} if !remove_content_button(:edit) %> 69 <%= expirable_button article, :edit, _('Edit'), {:action => 'edit', :id => article.id} if !remove_content_button(:edit) %>
70 <%= button_without_text :eyes, _('Public view'), article.view_url %> 70 <%= button_without_text :eyes, _('Public view'), article.view_url %>
71 <%= display_spread_button(profile, article) unless article.folder? || remove_content_button(:spread)%> 71 <%= display_spread_button(profile, article) unless article.folder? || remove_content_button(:spread)%>
72 - <% if !environment.enabled?('cant_change_homepage') && !remove_content_button(:home) %> 72 + <% if user.can_change_homepage? && !remove_content_button(:home) %>
73 <% if profile.home_page != article %> 73 <% if profile.home_page != article %>
74 <%= expirable_button article, :home, _('Use as homepage'), { :action => 'set_home_page', :id => article.id }, :method => :post %> 74 <%= expirable_button article, :home, _('Use as homepage'), { :action => 'set_home_page', :id => article.id }, :method => :post %>
75 <% else %> 75 <% else %>
app/views/contact/new.html.erb
@@ -13,11 +13,16 @@ @@ -13,11 +13,16 @@
13 13
14 <%= required_fields_message %> 14 <%= required_fields_message %>
15 15
16 - <% location_fields = select_city(true) %> 16 + <% unless logged_in? %>
  17 + <%= required f.text_field(:name) %>
  18 + <%= required f.text_field(:email) %>
  19 + <% end %>
17 20
  21 + <% location_fields = select_city(true) %>
18 <% unless environment.enabled?('disable_select_city_for_contact') || location_fields.blank? %> 22 <% unless environment.enabled?('disable_select_city_for_contact') || location_fields.blank? %>
19 <%= labelled_form_field _('City and state'), location_fields %> 23 <%= labelled_form_field _('City and state'), location_fields %>
20 <% end %> 24 <% end %>
  25 +
21 <%= required f.text_field(:subject) %> 26 <%= required f.text_field(:subject) %>
22 27
23 <%= render :file => 'shared/tiny_mce' %> 28 <%= render :file => 'shared/tiny_mce' %>
@@ -25,5 +30,9 @@ @@ -25,5 +30,9 @@
25 30
26 <%= labelled_form_field check_box(:contact, :receive_a_copy) + _('I want to receive a copy of the message in my e-mail.'), '' %> 31 <%= labelled_form_field check_box(:contact, :receive_a_copy) + _('I want to receive a copy of the message in my e-mail.'), '' %>
27 32
28 - <%= submit_button(:send, _('Send'), :onclick => "$('confirm').value = 'true'") %> 33 + <% unless logged_in? %>
  34 + <%= recaptcha_tags :ajax => true, :display => {:theme => 'clean'} %>
  35 + <% end %>
  36 +
  37 + <%= submit_button(:send, _('Send'), :onclick => "jQuery('#confirm').val('true')") %>
29 <% end %> 38 <% end %>
app/views/content_viewer/view_page.html.erb
@@ -70,37 +70,36 @@ @@ -70,37 +70,36 @@
70 70
71 <%= @plugins.dispatch(:article_extra_contents, @page).collect { |content| instance_exec(&content) }.join("") %> 71 <%= @plugins.dispatch(:article_extra_contents, @page).collect { |content| instance_exec(&content) }.join("") %>
72 72
73 -<div class="comments" id="comments_list">  
74 -  
75 - <% if @page.accept_comments? || @comments_count > 0 %> 73 +<% if @page.accept_comments? || @comments_count > 0 %>
  74 + <div class="comments" id="comments_list">
76 <h3 <%= 'class="no-comments-yet"' if @comments_count == 0 %>> 75 <h3 <%= 'class="no-comments-yet"' if @comments_count == 0 %>>
77 <%= display_number_of_comments(@comments_count) %> 76 <%= display_number_of_comments(@comments_count) %>
78 </h3> 77 </h3>
79 - <% end %>  
80 78
81 - <% if @comments.present? && @comments.count > 1 %>  
82 - <%= link_to(_('Post a comment'), '#', :class => 'display-comment-form', :id => 'top-post-comment-button', :onclick => "jQuery('#page-comment-form .display-comment-form').first().click();") if @page.accept_comments? %> 79 + <% if @comments.present? && @comments.count > 1 %>
  80 + <%= link_to(_('Post a comment'), '#', :class => 'display-comment-form', :id => 'top-post-comment-button', :onclick => "jQuery('#page-comment-form .display-comment-form').first().click();") if @page.accept_comments? %>
  81 +
  82 + <%= hidden_field_tag("page_url", url_for(:controller=>'content_viewer', :action=>'view_page', :profile=>profile.identifier, :page => @page.explode_path)) %>
  83 + <%= javascript_include_tag "comment_order.js" %>
  84 + <div class="comment-order">
  85 + <%= form_tag({:controller=>'content_viewer' , :action=>'view_page'}, {:method=>'get', :id=>"form_order"}) do %>
  86 + <%= select_tag 'comment_order', options_for_select({_('Oldest first')=>'oldest', _('Newest first')=>'newest'}, @comment_order) %>
  87 + <% end %>
  88 + </div>
  89 + <% end %>
83 90
84 - <%= hidden_field_tag("page_url", url_for(:controller=>'content_viewer', :action=>'view_page', :profile=>profile.identifier, :page => @page.explode_path)) %>  
85 - <%= javascript_include_tag "comment_order.js" %>  
86 - <div class="comment-order">  
87 - <%= form_tag({:controller=>'content_viewer' , :action=>'view_page'}, {:method=>'get', :id=>"form_order"}) do %>  
88 - <%= select_tag 'comment_order', options_for_select({_('Oldest first')=>'oldest', _('Newest first')=>'newest'}, @comment_order) %> 91 + <ul class="article-comments-list">
  92 + <% if @comments.present? %>
  93 + <%= render :partial => 'comment/comment', :collection => @comments %>
  94 + <%= pagination_links @comments, :param_name => 'comment_page' %>
89 <% end %> 95 <% end %>
90 - </div>  
91 - <% end %> 96 + </ul>
92 97
93 - <ul class="article-comments-list">  
94 - <% if @comments.present? %>  
95 - <%= render :partial => 'comment/comment', :collection => @comments %>  
96 - <%= pagination_links @comments, :param_name => 'comment_page' %> 98 + <% if @page.accept_comments? %>
  99 + <div id='page-comment-form' class='page-comment-form'><%= render :partial => 'comment/comment_form', :locals =>{:url => {:controller => :comment, :action => :create}, :display_link => true, :cancel_triggers_hide => true}%></div>
97 <% end %> 100 <% end %>
98 - </ul>  
99 -  
100 - <% if @page.accept_comments? %>  
101 - <div id='page-comment-form' class='page-comment-form'><%= render :partial => 'comment/comment_form', :locals =>{:url => {:controller => :comment, :action => :create}, :display_link => true, :cancel_triggers_hide => true}%></div>  
102 - <% end %>  
103 -</div><!-- end class="comments" --> 101 + </div><!-- end class="comments" -->
  102 +<% end %>
104 103
105 </div><!-- end id="article" --> 104 </div><!-- end id="article" -->
106 <%= add_zoom_to_article_images %> 105 <%= add_zoom_to_article_images %>
app/views/enterprise_registration/basic_information.html.erb
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 20
21 <%= labelled_form_for :create_enterprise do |f| %> 21 <%= labelled_form_for :create_enterprise do |f| %>
22 <%= required f.text_field 'name', :onchange => "updateUrlField(this, 'create_enterprise_identifier')", :size => 40 %> 22 <%= required f.text_field 'name', :onchange => "updateUrlField(this, 'create_enterprise_identifier')", :size => 40 %>
23 - <%= required labelled_form_field(_('Address'), content_tag('code', environment.top_url + "/" + text_field(:create_enterprise, 'identifier', :size => 26))) %> 23 + <%= required labelled_form_field(_('Address'), content_tag('code', top_url + "/" + text_field(:create_enterprise, 'identifier', :size => 26))) %>
24 <%= render :partial => 'shared/organization_custom_fields', :locals => { :f => f, :object_name => :create_enterprise, :profile => @create_enterprise } %> 24 <%= render :partial => 'shared/organization_custom_fields', :locals => { :f => f, :object_name => :create_enterprise, :profile => @create_enterprise } %>
25 <%= required labelled_form_field(_('Region'), f.select('region_id', @regions)) if @validation == :region %> 25 <%= required labelled_form_field(_('Region'), f.select('region_id', @regions)) if @validation == :region %>
26 26
app/views/events/_month.html.erb
@@ -13,8 +13,8 @@ @@ -13,8 +13,8 @@
13 date.day, 13 date.day,
14 :url => {:action => 'events_by_day', :year => date.year, :month => date.month, :day => date.day, :category_id => @category_id}, 14 :url => {:action => 'events_by_day', :year => date.year, :month => date.month, :day => date.day, :category_id => @category_id},
15 :update => 'events-of-the-day', 15 :update => 'events-of-the-day',
16 - :loading => '$("events-of-the-day").addClassName("loading")',  
17 - :complete => '$("events-of-the-day").removeClassName("loading")' 16 + :loading => "$('events-of-the-day').addClassName('loading')",
  17 + :complete => "$('events-of-the-day').removeClassName('loading')"
18 ) : 18 ) :
19 date.day 19 date.day
20 %> 20 %>
app/views/events/events.html.erb
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 <div id='agenda-toolbar'> 3 <div id='agenda-toolbar'>
4 <%= button :back, _('Back to %s') % profile.name, profile.url %> 4 <%= button :back, _('Back to %s') % profile.name, profile.url %>
5 <% if user && user.has_permission?('post_content', profile) %> 5 <% if user && user.has_permission?('post_content', profile) %>
6 - <%= button :new, _('New event'), myprofile_url(:controller => 'cms', :action => 'new', :type => 'Event') %> 6 + <%= button :new, _('New event'), myprofile_path(:controller => 'cms', :action => 'new', :type => 'Event') %>
7 <% end %> 7 <% end %>
8 </div> 8 </div>
9 9
app/views/file_presenter/_generic.html.erb
1 <span class="download-link"> 1 <span class="download-link">
2 <span>Download</span> 2 <span>Download</span>
3 - <strong><%= link_to generic.filename, generic.public_filename %></strong> 3 + <strong><%= link_to generic.filename, [Noosfero.root, generic.public_filename].join %></strong>
4 </span> 4 </span>
5 5
6 <div class="uploaded-file-description <%= 'empty' if generic.abstract.blank? %>"> 6 <div class="uploaded-file-description <%= 'empty' if generic.abstract.blank? %>">
app/views/file_presenter/_image.html.erb
@@ -28,7 +28,7 @@ @@ -28,7 +28,7 @@
28 28
29 <%# image_tag(article.public_filename(:display), :class => article.css_class_name, :style => 'max-width: 100%') %> 29 <%# image_tag(article.public_filename(:display), :class => article.css_class_name, :style => 'max-width: 100%') %>
30 30
31 -<img src="<%=image.public_filename(:display)%>" class="<%=image.css_class_name%>"> 31 +<img src="<%= [Noosfero.root, image.public_filename(:display)].join %>" class="<%=image.css_class_name%>">
32 32
33 <div class="uploaded-file-description <%= 'empty' if image.abstract.blank? %>"> 33 <div class="uploaded-file-description <%= 'empty' if image.abstract.blank? %>">
34 <%= image.abstract %> 34 <%= image.abstract %>
app/views/home/index.html.erb
@@ -61,9 +61,6 @@ @@ -61,9 +61,6 @@
61 <%= submit_button(:search, _('Search')) %> 61 <%= submit_button(:search, _('Search')) %>
62 </div> 62 </div>
63 63
64 - <div>  
65 - <%= lightbox_link_to _('More options'), :controller => 'search', :action => 'popup' %>  
66 - </div>  
67 <% end %> 64 <% end %>
68 </div> 65 </div>
69 <% end %> 66 <% end %>
app/views/layouts/_content.html.erb 0 → 100644
@@ -0,0 +1,4 @@ @@ -0,0 +1,4 @@
  1 +<div id="content-inner">
  2 + <%= insert_boxes(yield) %>
  3 + <br style='clear: both'/>
  4 +</div><!-- end id="content-inner" -->
app/views/layouts/application-ng.html.erb
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2 -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<%= html_language %>" lang="<%= html_language %>"> 2 +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<%= html_language %>" lang="<%= html_language %>" class="<%= h html_tag_classes %>">
3 <head> 3 <head>
4 <title><%= h page_title %></title> 4 <title><%= h page_title %></title>
5 <%= yield(:feeds) %> 5 <%= yield(:feeds) %>
@@ -12,20 +12,8 @@ @@ -12,20 +12,8 @@
12 <meta name="twitter:title" content="<%= h page_title %>"> 12 <meta name="twitter:title" content="<%= h page_title %>">
13 <meta name="twitter:description" content="<%= meta_description_tag(@page) %>"> 13 <meta name="twitter:description" content="<%= meta_description_tag(@page) %>">
14 14
15 - <!-- Open Graph -->  
16 - <meta property="og:type" content="<%= @page ? 'article' : 'website' %>">  
17 - <meta property="og:url" content="<%= @page ? url_for(@page.url) : @environment.top_url %>">  
18 - <meta property="og:title" content="<%= h page_title %>">  
19 - <meta property="og:site_name" content="<%= profile ? profile.name : @environment.name %>">  
20 - <meta property="og:description" content="<%= @page ? truncate(strip_tags(@page.body.to_s), :length => 200) : @environment.name %>">  
21 -  
22 - <% if @page %>  
23 - <meta property="article:published_time" content="<%= show_date(@page.published_at) %>">  
24 - <% @page.body_images_paths.each do |img| %>  
25 - <meta name="twitter:image" content="<%= img.to_s %>">  
26 - <meta property="og:image" content="<%= img.to_s %>">  
27 - <% end %>  
28 - <% end %> 15 + <!-- site root -->
  16 + <meta property="noosfero:root" content="<%= Noosfero.root %>"/>
29 17
30 <link rel="shortcut icon" href="<%= image_path(theme_favicon) %>" type="image/x-icon" /> 18 <link rel="shortcut icon" href="<%= image_path(theme_favicon) %>" type="image/x-icon" />
31 <%= noosfero_javascript %> 19 <%= noosfero_javascript %>
@@ -69,10 +57,7 @@ @@ -69,10 +57,7 @@
69 <div id="navigation-end"></div> 57 <div id="navigation-end"></div>
70 </div><!-- end id="navigation" --> 58 </div><!-- end id="navigation" -->
71 <div id="content"> 59 <div id="content">
72 - <div id="content-inner">  
73 - <%= insert_boxes(yield) %>  
74 - <br style='clear: both'/>  
75 - </div><!-- end id="content-inner" --> 60 + <%= render 'layouts/content' %>
76 </div><!-- end id="content" --> 61 </div><!-- end id="content" -->
77 </div><!-- end id="wrap-2" --> 62 </div><!-- end id="wrap-2" -->
78 </div><!-- end id="wrap-1" --> 63 </div><!-- end id="wrap-1" -->
@@ -81,7 +66,6 @@ @@ -81,7 +66,6 @@
81 <%= theme_footer %> 66 <%= theme_footer %>
82 </div><!-- end id="theme-footer" --> 67 </div><!-- end id="theme-footer" -->
83 <%= noosfero_layout_features %> 68 <%= noosfero_layout_features %>
84 - <%= theme_javascript_ng %>  
85 <%= addthis_javascript %> 69 <%= addthis_javascript %>
86 <%= 70 <%=
87 @plugins.dispatch(:body_ending).map do |content| 71 @plugins.dispatch(:body_ending).map do |content|
app/views/layouts/application.html.erb
1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 1 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
2 -<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<%= html_language %>" lang="<%= html_language %>"> 2 +<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="<%= html_language %>" lang="<%= html_language %>" class="<%= h html_tag_classes %>">
3 <head> 3 <head>
4 <title><%= h page_title %></title> 4 <title><%= h page_title %></title>
5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 5 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
@@ -68,7 +68,7 @@ @@ -68,7 +68,7 @@
68 68
69 <div id="navigation_bar"> 69 <div id="navigation_bar">
70 <%= link_to "<span>"+ @environment.name() +"</span>", 70 <%= link_to "<span>"+ @environment.name() +"</span>",
71 - @environment.top_url, 71 + top_url,
72 :id=>"menu_link_to_envhome", 72 :id=>"menu_link_to_envhome",
73 :title=>@environment.name %> 73 :title=>@environment.name %>
74 <% unless environment.enabled?(:disable_categories) %> 74 <% unless environment.enabled?(:disable_categories) %>
app/views/manage_products/_edit_description.html.erb
1 <%= render :file => 'shared/tiny_mce', :locals => {:mode => 'simple'} %> 1 <%= render :file => 'shared/tiny_mce', :locals => {:mode => 'simple'} %>
2 <%= remote_form_for(@product, 2 <%= remote_form_for(@product,
3 :loading => "small_loading('product-description-form')", 3 :loading => "small_loading('product-description-form')",
4 - :before => ("tinyMCE.triggerSave()" unless Rails.env == 'test'),  
5 :update => 'product-description', 4 :update => 'product-description',
6 :url => {:controller => 'manage_products', :action => 'edit', :id => @product, :field => 'description'}, 5 :url => {:controller => 'manage_products', :action => 'edit', :id => @product, :field => 'description'},
7 :html => {:id => 'product-description-form', :method => 'post'}) do |f| %> 6 :html => {:id => 'product-description-form', :method => 'post'}) do |f| %>
app/views/manage_products/_edit_info.html.erb
@@ -47,7 +47,7 @@ @@ -47,7 +47,7 @@
47 <%= button_to_function( 47 <%= button_to_function(
48 :add, 48 :add,
49 _('Add new qualifier'), 49 _('Add new qualifier'),
50 - "new_qualifier_row('#product-qualifiers-list', '#{escape_javascript(select_qualifiers(@product))}', '#{escape_javascript(remove_qualifier_button)}')" 50 + "new_qualifier_row('#product-qualifiers-list', '#{escape_javascript(CGI::escape_html(select_qualifiers(@product)))}', '#{escape_javascript(CGI::escape_html(remove_qualifier_button))}')"
51 ) %> 51 ) %>
52 <%= hidden_field_tag "product[qualifiers_list][nil]" %> 52 <%= hidden_field_tag "product[qualifiers_list][nil]" %>
53 <% end %> 53 <% end %>
app/views/manage_products/show.html.erb
@@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
13 <%= render :partial => 'manage_products/display_image' %> 13 <%= render :partial => 'manage_products/display_image' %>
14 </div> 14 </div>
15 <div id='product-extra-content'> 15 <div id='product-extra-content'>
16 - <% extra_content = @plugins.dispatch(:product_info_extras, @product).collect { |content| instance_eval(&content) } %> 16 + <% extra_content = @plugins.dispatch(:product_info_extras, @product).collect { |content| instance_exec(&content) } %>
17 <%= extra_content.join("\n") %> 17 <%= extra_content.join("\n") %>
18 </div> 18 </div>
19 <div id='product-info'> 19 <div id='product-info'>
app/views/profile/_common.html.erb
1 <% unless @action %> 1 <% unless @action %>
2 <% cache_timeout(profile.cache_key + '-profile-general-info', 4.hours) do %> 2 <% cache_timeout(profile.cache_key + '-profile-general-info', 4.hours) do %>
3 - <tr>  
4 - <th colspan='2'>  
5 - <%= _('Content') %>  
6 - </th>  
7 - </tr>  
8 -  
9 - <% profile.blogs.each do |blog| %>  
10 - <tr>  
11 - <td><%= blog.name + ':' %></td>  
12 - <td>  
13 - <%= link_to(n_('One post', '%{num} posts', blog.posts.published.count) % { :num => blog.posts.published.count }, blog.url) %>  
14 - </td>  
15 - </tr>  
16 - <% end %>  
17 - <% profile.image_galleries.each do |gallery| %>  
18 - <tr>  
19 - <td><%= gallery.name + ':' %></td>  
20 - <td>  
21 - <%= link_to(n_('One picture', '%{num} pictures', gallery.images.published.count) % { :num => gallery.images.published.count }, gallery.url) %>  
22 - </td>  
23 - </tr>  
24 - <% end %>  
25 -  
26 - <tr>  
27 - <td><%= _('Events:') %></td>  
28 - <td>  
29 - <%= link_to profile.events.published.count, :controller => 'events', :action => 'events' %>  
30 - </td>  
31 - </tr>  
32 - <tr>  
33 - <td>  
34 - <%= _('Tags:') %>  
35 - </td>  
36 - <td>  
37 - <%= tag_cloud @tags, :id, { :action => 'tags' }, :max_size => 18, :min_size => 10%>  
38 - </td>  
39 - </tr> 3 + <%= display_content %>
40 4
41 <% if !environment.enabled?('disable_categories') && !profile.interests.empty? %> 5 <% if !environment.enabled?('disable_categories') && !profile.interests.empty? %>
42 - <tr>  
43 - <th colspan='2'><%= _('Interests') %></th>  
44 - </tr>  
45 - <% profile.interests.each do |item| %>  
46 - <tr>  
47 - <td></td>  
48 - <td><%= link_to item.name, :controller => 'search', :action => 'category_index', :category_path => item.explode_path %></td>  
49 - </tr>  
50 - <% end %> 6 + <%= display_interests %>
51 <% end %> 7 <% end %>
  8 +
  9 + <%= display_general %>
52 <% end %> 10 <% end %>
53 <% end %> 11 <% end %>
app/views/profile/_organization_profile.html.erb
1 <table> 1 <table>
2 - <tr>  
3 - <th colspan='2'><%= _('Basic information')%></th>  
4 - </tr>  
5 -  
6 - <tr>  
7 - <td class='field-name'><%= _('Members') %></td>  
8 - <td>  
9 - <%= link_to profile.members_count, :controller => 'profile', :action => 'members' %>  
10 - </td>  
11 - </tr>  
12 -  
13 - <%= display_field(_('Type:'), profile, :privacy_setting, true) %>  
14 -  
15 - <%= display_field(_('Location:'), profile, :location, true) %>  
16 -  
17 - <tr>  
18 - <td class='field-name'><%= _('Profile created at:') %></td>  
19 - <td><%= show_date(profile.created_at) %></td>  
20 - </tr>  
21 -  
22 - <% if profile.kind_of?(Enterprise) && profile.environment.enabled?('products_for_enterprises') %>  
23 - <tr>  
24 - <td></td>  
25 - <td>  
26 - <%= link_to _('Products/Services'), :controller => 'catalog', :action => 'index' %>  
27 - </td>  
28 - </tr>  
29 - <% end %>  
30 -  
31 - <tr>  
32 - <td class='field-name'><%= _('Administrators:') %></td>  
33 - <td>  
34 - <%= profile.admins.map { |admin| link_to(admin.short_name, admin.url)}.join(', ') %>  
35 - </td>  
36 - </tr>  
37 - 2 + <%= display_basic_information %>
  3 + <%= display_contact %>
  4 + <%= display_economic %>
38 <%= render :partial => 'common' %> 5 <%= render :partial => 'common' %>
39 </table> 6 </table>
app/views/profile/_person_profile.html.erb
1 <table> 1 <table>
2 - <tr>  
3 - <th colspan='2'><%= _('Basic information')%></th>  
4 - </tr>  
5 - <%= display_field(_('Sex:'), profile, :sex) { |gender| { 'male' => _('Male'), 'female' => _('Female') }[gender] } %>  
6 - <%= display_field(_('Date of birth:'), profile, :birth_date) { |date| show_date(date) }%>  
7 - <%= display_field _('Location:'), profile, :location %>  
8 -  
9 - <%= display_field(_('Type:'), profile, :privacy_setting, true) %>  
10 -  
11 - <tr>  
12 - <td class='field-name'><%= _('Profile created at:') %></td>  
13 - <td><%= show_date(profile.created_at) %></td>  
14 - </tr>  
15 -  
16 - <%= display_contact profile %> 2 + <%= display_basic_information %>
  3 + <%= display_contact %>
  4 + <%= display_location %>
17 5
18 <% cache_timeout(profile.relationships_cache_key, 4.hours) do %> 6 <% cache_timeout(profile.relationships_cache_key, 4.hours) do %>
19 - <%= display_work_info profile %>  
20 -  
21 - <%= display_custom_fields(profile) %>  
22 -  
23 - <tr>  
24 - <th colspan='2'><%= _('Network')%></th>  
25 - </tr>  
26 - <tr>  
27 - <td><%= _('Friends') + ':' %></td>  
28 - <td><%= link_to profile.friends.count, { :controller => 'profile', :action => 'friends' } %></td>  
29 - </tr>  
30 - <tr>  
31 - <td><%= _('Communities') + ':' %></td>  
32 - <td><%= link_to profile.communities.count, :controller => "profile", :action => 'communities' %></td>  
33 - </tr>  
34 - <% if environment.disabled?('disable_asset_enterprises') %>  
35 - <tr id="person-profile-network-enterprises">  
36 - <td><%= _('Enterprises') + ':' %></td>  
37 - <td><%= link_to profile.enterprises.count, :controller => "profile", :action => 'enterprises' %></td>  
38 - </tr>  
39 - <% end %> 7 + <%= display_work %>
  8 + <%= display_study %>
  9 + <%= display_network %>
  10 + <%= display_custom_fields(profile) %>
40 11
41 <%= render :partial => 'common' %> 12 <%= render :partial => 'common' %>
42 -  
43 <% end %> 13 <% end %>
44 </table> 14 </table>
  15 +
app/views/profile/_profile_comment_form.html.erb
@@ -10,8 +10,8 @@ @@ -10,8 +10,8 @@
10 :rows => 1, 10 :rows => 1,
11 :class => 'submit-with-keypress', 11 :class => 'submit-with-keypress',
12 :title => _('Leave your comment'), 12 :title => _('Leave your comment'),
13 - :onfocus => ('if(this.value==this.title){this.value="";this.style.color="#000"};this.style.backgroundImage="url(' + profile_icon(current_person, :icon, false) + ')"' if logged_in?),  
14 - :onblur => ('if(this.value==""){this.value=this.title;this.style.color="#ccc"};this.style.backgroundImage="none"' if logged_in?), 13 + :onfocus => ("if(this.value==this.title){this.value='';this.style.color='#000'};this.style.backgroundImage='url(" + profile_icon(current_person, :icon, false) + ")'" if logged_in?),
  14 + :onblur => ("if(this.value==''){this.value=this.title;this.style.color='#ccc'};this.style.backgroundImage='none'" if logged_in?),
15 :value => _('Leave your comment'), 15 :value => _('Leave your comment'),
16 :style => 'color: #ccc' %> 16 :style => 'color: #ccc' %>
17 <%= hidden_field_tag :source_id, activity.id, :id => "activity_id_#{activity.id}" %> 17 <%= hidden_field_tag :source_id, activity.id, :id => "activity_id_#{activity.id}" %>
app/views/profile/_profile_scrap_reply_form.html.erb
@@ -9,8 +9,8 @@ @@ -9,8 +9,8 @@
9 :rows => 1, 9 :rows => 1,
10 :class => 'submit-with-keypress', 10 :class => 'submit-with-keypress',
11 :title => _('Leave your comment'), 11 :title => _('Leave your comment'),
12 - :onfocus => ('if(this.value==this.title){this.value="";this.style.color="#000"};this.style.backgroundImage="url(' + profile_icon(current_person, :icon, false) + ')"' if logged_in?),  
13 - :onblur => ('if(this.value==""){this.value=this.title;this.style.color="#ccc"};this.style.backgroundImage="none"' if logged_in?), 12 + :onfocus => ("if(this.value==this.title){this.value='';this.style.color='#000'};this.style.backgroundImage='url(" + profile_icon(current_person, :icon, false) + ")'" if logged_in?),
  13 + :onblur => ("if(this.value==''){this.value=this.title;this.style.color='#ccc'};this.style.backgroundImage='none'" if logged_in?),
14 :value => _('Leave your comment') %> 14 :value => _('Leave your comment') %>
15 <%= hidden_field_tag 'scrap[scrap_id]', scrap.id %> 15 <%= hidden_field_tag 'scrap[scrap_id]', scrap.id %>
16 <%= hidden_field_tag 'receiver_id', scrap.sender.id %> 16 <%= hidden_field_tag 'receiver_id', scrap.sender.id %>
app/views/profile_editor/_person_form.html.erb
@@ -25,6 +25,11 @@ @@ -25,6 +25,11 @@
25 <%= optional_field(@person, 'address', labelled_form_field(_('Address (street and number)'), text_field(:profile_data, :address, :rel => _('Address')))) %> 25 <%= optional_field(@person, 'address', labelled_form_field(_('Address (street and number)'), text_field(:profile_data, :address, :rel => _('Address')))) %>
26 <%= optional_field(@person, 'address_reference', labelled_form_field(_('Address reference'), text_field(:profile_data, :address_reference, :rel => _('Address reference')))) %> 26 <%= optional_field(@person, 'address_reference', labelled_form_field(_('Address reference'), text_field(:profile_data, :address_reference, :rel => _('Address reference')))) %>
27 <%= optional_field(@person, 'district', labelled_form_field(_('District'), text_field(:profile_data, :district, :rel => _('District')))) %> 27 <%= optional_field(@person, 'district', labelled_form_field(_('District'), text_field(:profile_data, :district, :rel => _('District')))) %>
  28 +<%= optional_field(@person, 'image', labelled_form_field(_('Image'), file_field(:file, :image, :rel => _('Image')))) %>
  29 +
  30 +<% @plugins.dispatch(:extra_optional_fields).each do |field| %>
  31 + <%= optional_field(@person, field[:name], labelled_form_field(field[:label], text_field(field[:object_name], field[:method], :rel => field[:label], :value => field[:value]))) %>
  32 +<% end %>
28 33
29 <% optional_field(@person, 'schooling') do %> 34 <% optional_field(@person, 'schooling') do %>
30 <div class="formfieldline"> 35 <div class="formfieldline">
app/views/profile_editor/edit.html.erb
1 <h1><%= _('Profile settings for %s') % profile.name %></h1> 1 <h1><%= _('Profile settings for %s') % profile.name %></h1>
2 2
  3 +<%= javascript_include_tag 'deactivate_profile' %>
3 <%= error_messages_for :profile_data %> 4 <%= error_messages_for :profile_data %>
4 5
5 <%= labelled_form_for :profile_data, :html => { :id => 'profile-data', :multipart => true } do |f| %> 6 <%= labelled_form_for :profile_data, :html => { :id => 'profile-data', :multipart => true } do |f| %>
@@ -67,6 +68,15 @@ @@ -67,6 +68,15 @@
67 <% if user && user.has_permission?('destroy_profile', profile) %> 68 <% if user && user.has_permission?('destroy_profile', profile) %>
68 <% button_bar(:id => 'delete-profile') do %> 69 <% button_bar(:id => 'delete-profile') do %>
69 <%= button(:remove, _('Delete profile'), {:action => :destroy_profile}) %> 70 <%= button(:remove, _('Delete profile'), {:action => :destroy_profile}) %>
  71 +
  72 + <% if environment.admins.include?(current_person) %>
  73 +
  74 + <% if profile.visible? %>
  75 + <%= button(:remove, _('Deactivate profile'), {:action => :deactivate_profile, :id=>profile.id}, :id=>'deactivate_profile_button', :data => {:confirm=>_("Are you sure you want to deactivate this profile?")}) %>
  76 + <% else %>
  77 + <%= button(:add, _('Activate profile'), {:action => :activate_profile, :id=>profile.id}, :data => {:confirm=>_("Are you sure you want to deactivate this profile?")}) %>
  78 + <% end %>
  79 + <% end %>
70 <% end %> 80 <% end %>
71 <% end %> 81 <% end %>
72 -<% end %> 82 -<% end %>
  83 +<% end %>
73 \ No newline at end of file 84 \ No newline at end of file
app/views/role/_form.html.erb
@@ -6,10 +6,14 @@ @@ -6,10 +6,14 @@
6 6
7 <%= required f.text_field(:name) %> 7 <%= required f.text_field(:name) %>
8 8
9 - <p><%= _('Permissions:') %><p>  
10 - <% permissions.keys.each do |p| %>  
11 - <%= check_box_tag("role[permissions][]", p, role.has_permission?(p), { :id => p }) %>  
12 - <%= content_tag(:label, permission_name(p), { :for => p }) %><br/> 9 + <% permissions.each do |key| %>
  10 + <div class="permissions <%= key.downcase %>">
  11 + <h4><%= _('%s Permissions:' % key) %></h4>
  12 + <% ActiveRecord::Base::PERMISSIONS[key].keys.each do |p| %>
  13 + <%= check_box_tag("role[permissions][]", p, role.has_permission?(p), { :id => p }) %>
  14 + <%= content_tag(:label, permission_name(p), { :for => p }) %><br/>
  15 + <% end %>
  16 + </div>
13 <% end %> 17 <% end %>
14 18
15 <% button_bar do %> 19 <% button_bar do %>
app/views/role/edit.html.erb
1 <h2> <%= _("Editing #{@role.name}") %> </h2> 1 <h2> <%= _("Editing #{@role.name}") %> </h2>
2 2
3 -<%= render :partial => 'form', :locals => { :mode => :edit, :role => @role, :permissions => ActiveRecord::Base::PERMISSIONS[@role.kind] } %> 3 +<%= render :partial => 'form', :locals => { :mode => :edit, :role => @role, :permissions => role_available_permissions(@role) } %>
app/views/role/new.html.erb
1 <h2> <%= _("Create a new role") %> </h2> 1 <h2> <%= _("Create a new role") %> </h2>
2 2
3 -<%= render :partial => 'form', :locals => { :mode => :create, :role => @role, :permissions => ActiveRecord::Base::PERMISSIONS[@role.kind] } %> 3 +<%= render :partial => 'form', :locals => { :mode => :create, :role => @role, :permissions => role_available_permissions(@role) } %>
app/views/search/_display_results.html.erb
@@ -14,7 +14,7 @@ @@ -14,7 +14,7 @@
14 14
15 <% display = display_filter(name, params[:display]) %> 15 <% display = display_filter(name, params[:display]) %>
16 16
17 - <div class="search-results-innerbox search-results-type-<%= name.to_s.singularize %> <%= 'common-profile-list-block' if [:enterprises, :people, :communities].include?(name) %>"> 17 + <div class="search-results-innerbox search-results-type-<%= name.to_s.singularize %> <%= 'common-profile-list-block' if SearchHelper::COMMON_PROFILE_LIST_BLOCK.include?(name) %>">
18 <ul> 18 <ul>
19 <% search[:results].each do |hit| %> 19 <% search[:results].each do |hit| %>
20 <% partial = partial_for_class(hit.class, display) %> 20 <% partial = partial_for_class(hit.class, display) %>
app/views/shared/reported_versions/_article.html.erb
@@ -1,10 +0,0 @@ @@ -1,10 +0,0 @@
1 -<ul>  
2 - <li><%= (content_tag('strong', _('Title') + ': ') + article.title) if article.title %> </li>  
3 - <li><%= (content_tag('strong', _('Type') + ': ') + article.class.short_description) %> </li>  
4 - <li>  
5 - <%= (content_tag('strong', _('Original content') + ': ') + link_to(article.name, article.url)) %> <br />  
6 - <%= content_tag('small', _('This link might be unavailable if the content is removed')) %>  
7 - </li>  
8 -</ul>  
9 -  
10 -<%= article_to_html(article) %>  
app/views/shared/reported_versions/_comment.html.erb
@@ -1,10 +0,0 @@ @@ -1,10 +0,0 @@
1 -<ul>  
2 - <li><%= (content_tag('strong', _('Title') + ': ') + comment.title) if comment.title %> </li>  
3 - <li><%= content_tag('strong', _('Type') + ': ') + _('Comment') %> </li>  
4 - <li>  
5 - <%= (content_tag('strong', _('Original content') + ': ') + link_to(comment.title || url_for(comment.url), comment.url)) %> <br />  
6 - <%= content_tag('small', _('This link might be unavailable if the content is removed')) %>  
7 - </li>  
8 -</ul>  
9 -  
10 -<p><%= article_to_html(comment) %></p>  
app/views/shared/reported_versions/_folder.html.erb
@@ -1 +0,0 @@ @@ -1 +0,0 @@
1 -<%= _('Reported folder') + ': ' + link_to(article.name, article.url) %>  
app/views/shared/reported_versions/profile/_article.html.erb 0 → 100644
@@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
  1 +<ul>
  2 + <li><%= (content_tag('strong', _('Title') + ': ') + article.title) if article.title %> </li>
  3 + <li><%= (content_tag('strong', _('Type') + ': ') + article.class.short_description) %> </li>
  4 + <li>
  5 + <%= (content_tag('strong', _('Original content') + ': ') + link_to(article.name, article.url)) %> <br />
  6 + <%= content_tag('small', _('This link might be unavailable if the content is removed')) %>
  7 + </li>
  8 +</ul>
  9 +
  10 +<%= article_to_html(article) %>
app/views/shared/reported_versions/profile/_comment.html.erb 0 → 100644
@@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
  1 +<ul>
  2 + <li><%= (content_tag('strong', _('Title') + ': ') + comment.title) if comment.title %> </li>
  3 + <li><%= content_tag('strong', _('Type') + ': ') + _('Comment') %> </li>
  4 + <li>
  5 + <%= (content_tag('strong', _('Original content') + ': ') + link_to(comment.title || url_for(comment.url), comment.url)) %> <br />
  6 + <%= content_tag('small', _('This link might be unavailable if the content is removed')) %>
  7 + </li>
  8 +</ul>
  9 +
  10 +<p><%= article_to_html(comment) %></p>
app/views/shared/reported_versions/profile/_folder.html.erb 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +<%= _('Reported folder') + ': ' + link_to(article.name, article.url) %>