Commit 0972e95be44b802575d91a35bbe66e97f98ef0df

Authored by Rodrigo Souto
2 parents 57c5f59d 80bac445

Merge branch 'chat' of gitlab.com:diguliu/noosfero into chat

Conflicts:
	public/javascripts/chat.js
Showing 1339 changed files with 36096 additions and 100756 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 1339 files displayed.

@@ -40,6 +40,7 @@ Alessandro Palmeira + João M. M. Silva <alessandro.palmeira@gmail.com> @@ -40,6 +40,7 @@ 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>
44 Andre Bernardes <andrebsguedes@gmail.com> 45 Andre Bernardes <andrebsguedes@gmail.com>
45 Antonio Terceiro + Carlos Morais <terceiro@colivre.coop.br> 46 Antonio Terceiro + Carlos Morais <terceiro@colivre.coop.br>
@@ -81,7 +82,6 @@ Carlos Morais + Diego Araújo &lt;diegoamc90@gmail.com&gt; @@ -81,7 +82,6 @@ Carlos Morais + Diego Araújo &lt;diegoamc90@gmail.com&gt;
81 Carlos Morais + Eduardo Morais <carlos88morais@gmail.com> 82 Carlos Morais + Eduardo Morais <carlos88morais@gmail.com>
82 Carlos Morais + Paulo Meirelles <carlos88morais@gmail.com> 83 Carlos Morais + Paulo Meirelles <carlos88morais@gmail.com>
83 Carlos Morais + Pedro Leal <carlos88morais@gmail.com> 84 Carlos Morais + Pedro Leal <carlos88morais@gmail.com>
84 -Daniela Feitosa <dani@dohko.(none)>  
85 Daniel Alves + Diego Araújo <danpaulalves@gmail.com> 85 Daniel Alves + Diego Araújo <danpaulalves@gmail.com>
86 Daniel Alves + Diego Araújo <diegoamc90@gmail.com> 86 Daniel Alves + Diego Araújo <diegoamc90@gmail.com>
87 Daniel Alves + Diego Araújo + Guilherme Rojas <danpaulalves@gmail.com> 87 Daniel Alves + Diego Araújo + Guilherme Rojas <danpaulalves@gmail.com>
@@ -119,7 +119,6 @@ Diego Araújo + Renan Teruo &lt;diegoamc90@gmail.com&gt; @@ -119,7 +119,6 @@ Diego Araújo + Renan Teruo &lt;diegoamc90@gmail.com&gt;
119 Diego Araujo + Rodrigo Souto + Rafael Manzo <rr.manzo@gmail.com> 119 Diego Araujo + Rodrigo Souto + Rafael Manzo <rr.manzo@gmail.com>
120 Diego + Jefferson <diegoamc90@gmail.com> 120 Diego + Jefferson <diegoamc90@gmail.com>
121 Diego Martinez <diegoamc90@gmail.com> 121 Diego Martinez <diegoamc90@gmail.com>
122 -Diego Martinez <diego@diego-K55A.(none)>  
123 Diego + Renan <renanteruoc@gmail.com> 122 Diego + Renan <renanteruoc@gmail.com>
124 Eduardo Tourinho Edington <eduardo.edington@serpro.gov.br> 123 Eduardo Tourinho Edington <eduardo.edington@serpro.gov.br>
125 Evandro Jr <evandrojr@gmail.com> 124 Evandro Jr <evandrojr@gmail.com>
@@ -195,9 +194,11 @@ Luis David Aguilar Carlos &lt;ludwig9003@gmail.com&gt; @@ -195,9 +194,11 @@ Luis David Aguilar Carlos &lt;ludwig9003@gmail.com&gt;
195 Luiz Fernando de Freitas Matos <luiz@luizff.matos@gmail.com> 194 Luiz Fernando de Freitas Matos <luiz@luizff.matos@gmail.com>
196 Marcos Ramos <ms.ramos@outlook.com> 195 Marcos Ramos <ms.ramos@outlook.com>
197 Martín Olivera <molivera@solar.org.ar> 196 Martín Olivera <molivera@solar.org.ar>
  197 +Michal Čihař <michal@cihar.com>
198 Moises Machado <moises@colivre.coop.br> 198 Moises Machado <moises@colivre.coop.br>
199 Naíla Alves <naila@colivre.coop.br> 199 Naíla Alves <naila@colivre.coop.br>
200 Nanda Lopes <nanda.listas+psl@gmail.com> 200 Nanda Lopes <nanda.listas+psl@gmail.com>
  201 +Parley Martins <parleypachecomartins@gmail.com>
201 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>
202 Paulo Meirelles + Alessandro Palmeira <paulo@softwarelivre.org> 203 Paulo Meirelles + Alessandro Palmeira <paulo@softwarelivre.org>
203 Paulo Meirelles + Carlos Morais <paulo@softwarelivre.org> 204 Paulo Meirelles + Carlos Morais <paulo@softwarelivre.org>
@@ -220,6 +221,7 @@ Rafael Reggiani Manzo + João M. M. da Silva &lt;rr.manzo@gmail.com&gt; @@ -220,6 +221,7 @@ Rafael Reggiani Manzo + João M. M. da Silva &lt;rr.manzo@gmail.com&gt;
220 Rafael Reggiani Manzo <rr.manzo@gmail.com> 221 Rafael Reggiani Manzo <rr.manzo@gmail.com>
221 Raphaël Rousseau <raph@r4f.org> 222 Raphaël Rousseau <raph@r4f.org>
222 Raquel Lira <raquel.lira@gmail.com> 223 Raquel Lira <raquel.lira@gmail.com>
  224 +Raquel <rcordioli@gmail.com>
223 Renan Teruo + Caio Salgado <renanteruoc@gmail.com> 225 Renan Teruo + Caio Salgado <renanteruoc@gmail.com>
224 Renan Teruoc + Diego Araujo <renanteruoc@gmail.com> 226 Renan Teruoc + Diego Araujo <renanteruoc@gmail.com>
225 Renan Teruo + Diego Araujo <renanteruoc@gmail.com> 227 Renan Teruo + Diego Araujo <renanteruoc@gmail.com>
@@ -227,13 +229,13 @@ Renan Teruo + Diego Araújo &lt;renanteruoc@gmail.com&gt; @@ -227,13 +229,13 @@ Renan Teruo + Diego Araújo &lt;renanteruoc@gmail.com&gt;
227 Renan Teruo + Paulo Meirelles <renanteruoc@gmail.com> 229 Renan Teruo + Paulo Meirelles <renanteruoc@gmail.com>
228 Renan Teruo + Rafael Manzo <renanteruoc@gmail.com> 230 Renan Teruo + Rafael Manzo <renanteruoc@gmail.com>
229 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>
230 -Rodrigo Souto <diguliu@gmail.com>  
231 Rodrigo Souto <rodrigo@colivre.coop.br> 232 Rodrigo Souto <rodrigo@colivre.coop.br>
232 Ronny Kursawe <kursawe.ronny@googlemail.com> 233 Ronny Kursawe <kursawe.ronny@googlemail.com>
233 root <root@debian.sdr.serpro> 234 root <root@debian.sdr.serpro>
234 Samuel R. C. Vale <srcvale@holoscopio.com> 235 Samuel R. C. Vale <srcvale@holoscopio.com>
235 Tallys Martins <tallysmartins@gmail.com> 236 Tallys Martins <tallysmartins@gmail.com>
236 tallys <tallys@tallys.(none)> 237 tallys <tallys@tallys.(none)>
  238 +Thiago Zoroastro <thiago.zoroastro@bol.com.br>
237 Valessio Brito <contato@valessiobrito.com.br> 239 Valessio Brito <contato@valessiobrito.com.br>
238 Valessio Brito <contato@valessiobrito.info> 240 Valessio Brito <contato@valessiobrito.info>
239 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.2.19' 2 gem 'rails', '~> 3.2.19'
  3 +gem 'minitest', '~> 3.2.0'
3 gem 'fast_gettext', '~> 0.6.8' 4 gem 'fast_gettext', '~> 0.6.8'
4 gem 'acts-as-taggable-on', '~> 3.0.2' 5 gem 'acts-as-taggable-on', '~> 3.0.2'
5 gem 'prototype-rails', '~> 3.2.1' 6 gem 'prototype-rails', '~> 3.2.1'
@@ -18,6 +19,7 @@ gem &#39;rake&#39;, :require =&gt; false @@ -18,6 +19,7 @@ gem &#39;rake&#39;, :require =&gt; false
18 gem 'rest-client', '~> 1.6.7' 19 gem 'rest-client', '~> 1.6.7'
19 gem 'exception_notification', '~> 4.0.1' 20 gem 'exception_notification', '~> 4.0.1'
20 gem 'gettext', '~> 2.2.1', :require => false, :group => :development 21 gem 'gettext', '~> 2.2.1', :require => false, :group => :development
  22 +gem 'locale', '~> 2.0.5'
21 23
22 # FIXME list here all actual dependencies (i.e. the ones in debian/control), 24 # FIXME list here all actual dependencies (i.e. the ones in debian/control),
23 # with their GEM names (not the Debian package names) 25 # with their GEM names (not the Debian package names)
@@ -40,8 +42,9 @@ group :cucumber do @@ -40,8 +42,9 @@ group :cucumber do
40 gem 'selenium-webdriver', '~> 2.39.0' 42 gem 'selenium-webdriver', '~> 2.39.0'
41 end 43 end
42 44
43 -# include plugin gemfiles  
44 -Dir.glob(File.join('config', 'plugins', '*')).each do |plugin|  
45 - plugin_gemfile = File.join(plugin, 'Gemfile')  
46 - eval File.read(plugin_gemfile) if File.exists?(plugin_gemfile) 45 +# include gemfiles from enabled plugins
  46 +# plugins in baseplugins/ are not included on purpose. They should not have any
  47 +# dependencies.
  48 +Dir.glob('config/plugins/*/Gemfile').each do |gemfile|
  49 + eval File.read(gemfile)
47 end 50 end
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 ================================
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
@@ -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
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
@@ -16,14 +16,16 @@ class ProfileEditorController &lt; MyProfileController @@ -16,14 +16,16 @@ class ProfileEditorController &lt; MyProfileController
16 if request.post? 16 if request.post?
17 params[:profile_data][:fields_privacy] ||= {} if profile.person? && params[:profile_data].is_a?(Hash) 17 params[:profile_data][:fields_privacy] ||= {} if profile.person? && params[:profile_data].is_a?(Hash)
18 Profile.transaction do 18 Profile.transaction do
19 - Image.transaction do  
20 - if @profile_data.update_attributes(params[:profile_data])  
21 - redirect_to :action => 'index', :profile => profile.identifier  
22 - else  
23 - profile.identifier = params[:profile] if profile.identifier.blank? 19 + Image.transaction do
  20 + begin
  21 + @plugins.dispatch(:profile_editor_transaction_extras)
  22 + @profile_data.update_attributes!(params[:profile_data])
  23 + redirect_to :action => 'index', :profile => profile.identifier
  24 + rescue Exception => ex
  25 + profile.identifier = params[:profile] if profile.identifier.blank?
  26 + end
24 end 27 end
25 end 28 end
26 - end  
27 end 29 end
28 end 30 end
29 31
@@ -72,10 +74,51 @@ class ProfileEditorController &lt; MyProfileController @@ -72,10 +74,51 @@ class ProfileEditorController &lt; MyProfileController
72 if request.post? 74 if request.post?
73 if @profile.destroy 75 if @profile.destroy
74 session[:notice] = _('The profile was deleted.') 76 session[:notice] = _('The profile was deleted.')
75 - redirect_to :controller => 'home' 77 + if(params[:return_to])
  78 + redirect_to params[:return_to]
  79 + else
  80 + redirect_to :controller => 'home'
  81 + end
76 else 82 else
77 session[:notice] = _('Could not delete profile') 83 session[:notice] = _('Could not delete profile')
78 end 84 end
79 end 85 end
80 end 86 end
  87 +
  88 + def deactivate_profile
  89 + if environment.admins.include?(current_person)
  90 + profile = environment.profiles.find(params[:id])
  91 + if profile.disable
  92 + profile.save
  93 + session[:notice] = _("The profile '#{profile.name}' was deactivated.")
  94 + else
  95 + session[:notice] = _('Could not deactivate profile.')
  96 + end
  97 + end
  98 +
  99 + redirect_to_previous_location
  100 + end
  101 +
  102 + def activate_profile
  103 + if environment.admins.include?(current_person)
  104 + profile = environment.profiles.find(params[:id])
  105 +
  106 + if profile.enable
  107 + session[:notice] = _("The profile '#{profile.name}' was activated.")
  108 + else
  109 + session[:notice] = _('Could not activate the profile.')
  110 + end
  111 + end
  112 +
  113 + redirect_to_previous_location
  114 + end
  115 +
  116 + protected
  117 +
  118 + def redirect_to_previous_location
  119 + back = request.referer
  120 + back = "/" if back.nil?
  121 +
  122 + redirect_to back
  123 + end
81 end 124 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
@@ -193,7 +193,7 @@ class AccountController &lt; ApplicationController @@ -193,7 +193,7 @@ class AccountController &lt; ApplicationController
193 else 193 else
194 @change_password.errors[:base] << _('Could not find any user with %s equal to "%s".') % [fields_label, params[:value]] 194 @change_password.errors[:base] << _('Could not find any user with %s equal to "%s".') % [fields_label, params[:value]]
195 end 195 end
196 - rescue ActiveRecord::RecordInvald 196 + rescue ActiveRecord::RecordInvalid
197 @change_password.errors[:base] << _('Could not perform password recovery for the user.') 197 @change_password.errors[:base] << _('Could not perform password recovery for the user.')
198 end 198 end
199 end 199 end
app/controllers/public/chat_controller.rb
@@ -6,6 +6,7 @@ class ChatController &lt; PublicController @@ -6,6 +6,7 @@ class ChatController &lt; PublicController
6 def start_session 6 def start_session
7 login = user.jid 7 login = user.jid
8 password = current_user.crypted_password 8 password = current_user.crypted_password
  9 + session[:chat] ||= {:rooms => []}
9 begin 10 begin
10 jid, sid, rid = RubyBOSH.initialize_session(login, password, "http://#{environment.default_hostname}/http-bind", 11 jid, sid, rid = RubyBOSH.initialize_session(login, password, "http://#{environment.default_hostname}/http-bind",
11 :wait => 30, :hold => 1, :window => 5) 12 :wait => 30, :hold => 1, :window => 5)
@@ -16,10 +17,35 @@ class ChatController &lt; PublicController @@ -16,10 +17,35 @@ class ChatController &lt; PublicController
16 end 17 end
17 end 18 end
18 19
  20 + def toggle
  21 + session[:chat][:status] = session[:chat][:status] == 'opened' ? 'closed' : 'opened'
  22 + render :nothing => true
  23 + end
  24 +
  25 + def tab
  26 + session[:chat][:tab_id] = params[:tab_id]
  27 + render :nothing => true
  28 + end
  29 +
  30 + def join
  31 + session[:chat][:rooms] << params[:room_id]
  32 + session[:chat][:rooms].uniq!
  33 + render :nothing => true
  34 + end
  35 +
  36 + def leave
  37 + session[:chat][:rooms].delete(params[:room_id])
  38 + render :nothing => true
  39 + end
  40 +
  41 + def my_session
  42 + render :text => session[:chat].to_json, :layout => false
  43 + end
  44 +
19 def avatar 45 def avatar
20 profile = environment.profiles.find_by_identifier(params[:id]) 46 profile = environment.profiles.find_by_identifier(params[:id])
21 filename, mimetype = profile_icon(profile, :minor, true) 47 filename, mimetype = profile_icon(profile, :minor, true)
22 - if filename =~ /^https?:/ 48 + if filename =~ /^(https?:)?\/\//
23 redirect_to filename 49 redirect_to filename
24 else 50 else
25 data = File.read(File.join(Rails.root, 'public', filename)) 51 data = File.read(File.join(Rails.root, 'public', filename))
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
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
@@ -674,13 +674,14 @@ module ApplicationHelper @@ -674,13 +674,14 @@ module ApplicationHelper
674 html.join "\n" 674 html.join "\n"
675 end 675 end
676 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 +
677 def theme_javascript_ng 682 def theme_javascript_ng
678 - script = File.join(theme_path, 'theme.js')  
679 - if File.exists?(File.join(Rails.root, 'public', script))  
680 - javascript_include_tag script  
681 - else  
682 - nil  
683 - end 683 + script = theme_javascript_src
  684 + javascript_include_tag script if script
684 end 685 end
685 686
686 def file_field_or_thumbnail(label, image, i) 687 def file_field_or_thumbnail(label, image, i)
@@ -861,8 +862,9 @@ module ApplicationHelper @@ -861,8 +862,9 @@ module ApplicationHelper
861 end 862 end
862 863
863 def base_url 864 def base_url
864 - environment.top_url 865 + environment.top_url(request.scheme)
865 end 866 end
  867 + alias :top_url :base_url
866 868
867 def helper_for_article(article) 869 def helper_for_article(article)
868 article_helper = ActionView::Base.new 870 article_helper = ActionView::Base.new
@@ -907,13 +909,15 @@ module ApplicationHelper @@ -907,13 +909,15 @@ module ApplicationHelper
907 end 909 end
908 910
909 def page_title 911 def page_title
910 - (@page ? @page.title + ' - ' : '') +  
911 - (@topic ? @topic.title + ' - ' : '') +  
912 - (@section ? @section.title + ' - ' : '') +  
913 - (@toc ? _('Online Manual') + ' - ' : '') +  
914 - (controller.controller_name == 'chat' ? _('Chat') + ' - ' : '') +  
915 - (profile ? profile.short_name : environment.name) +  
916 - (@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 + )
917 end 921 end
918 922
919 # DEPRECATED. Do not use this. 923 # DEPRECATED. Do not use this.
@@ -942,9 +946,9 @@ module ApplicationHelper @@ -942,9 +946,9 @@ module ApplicationHelper
942 # from Article model for an ArticleBlock. 946 # from Article model for an ArticleBlock.
943 def reference_to_article(text, article, anchor=nil) 947 def reference_to_article(text, article, anchor=nil)
944 if article.profile.domains.empty? 948 if article.profile.domains.empty?
945 - href = "/#{article.url[:profile]}/" 949 + href = "#{Noosfero.root}/#{article.url[:profile]}/"
946 else 950 else
947 - href = "http://#{article.profile.domains.first.name}/" 951 + href = "http://#{article.profile.domains.first.name}#{Noosfero.root}/"
948 end 952 end
949 href += article.url[:page].join('/') 953 href += article.url[:page].join('/')
950 href += '#' + anchor if anchor 954 href += '#' + anchor if anchor
@@ -1285,11 +1289,13 @@ module ApplicationHelper @@ -1285,11 +1289,13 @@ module ApplicationHelper
1285 end 1289 end
1286 1290
1287 def delete_article_message(article) 1291 def delete_article_message(article)
1288 - if article.folder?  
1289 - _("Are you sure that you want to remove the folder \"%s\"? Note that all the items inside it will also be removed!") % article.name  
1290 - else  
1291 - _("Are you sure that you want to remove the item \"%s\"?") % article.name  
1292 - 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 + )
1293 end 1299 end
1294 1300
1295 def expirable_link_to(expired, content, url, options = {}) 1301 def expirable_link_to(expired, content, url, options = {})
@@ -1310,10 +1316,8 @@ module ApplicationHelper @@ -1310,10 +1316,8 @@ module ApplicationHelper
1310 return '' if templates.count == 0 1316 return '' if templates.count == 0
1311 return hidden_field_tag("#{field_name}[template_id]", templates.first.id) if templates.count == 1 1317 return hidden_field_tag("#{field_name}[template_id]", templates.first.id) if templates.count == 1
1312 1318
1313 - counter = 0  
1314 radios = templates.map do |template| 1319 radios = templates.map do |template|
1315 - counter += 1  
1316 - content_tag('li', labelled_radio_button(link_to(template.name, template.url, :target => '_blank'), "#{field_name}[template_id]", template.id, counter==1)) 1320 + 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)))
1317 end.join("\n") 1321 end.join("\n")
1318 1322
1319 content_tag('div', content_tag('label', _('Profile organization'), :for => 'template-options', :class => 'formlabel') + 1323 content_tag('div', content_tag('label', _('Profile organization'), :for => 'template-options', :class => 'formlabel') +
@@ -1377,7 +1381,7 @@ module ApplicationHelper @@ -1377,7 +1381,7 @@ module ApplicationHelper
1377 # are old things that do not support it we are keeping this hot spot. 1381 # are old things that do not support it we are keeping this hot spot.
1378 html = @plugins.pipeline(:parse_content, html, source).first 1382 html = @plugins.pipeline(:parse_content, html, source).first
1379 end 1383 end
1380 - html 1384 + html && html.html_safe
1381 end 1385 end
1382 1386
1383 def convert_macro(html, source) 1387 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
@@ -85,6 +106,10 @@ module LayoutHelper @@ -85,6 +106,10 @@ module LayoutHelper
85 theme_path + '/style.css' 106 theme_path + '/style.css'
86 end 107 end
87 108
  109 + def layout_template
  110 + if profile then profile.layout_template else environment.layout_template end
  111 + end
  112 +
88 def addthis_javascript 113 def addthis_javascript
89 if NOOSFERO_CONF['addthis_enabled'] 114 if NOOSFERO_CONF['addthis_enabled']
90 '<script src="https://s7.addthis.com/js/152/addthis_widget.js"></script>' 115 '<script src="https://s7.addthis.com/js/152/addthis_widget.js"></script>'
@@ -92,7 +117,7 @@ module LayoutHelper @@ -92,7 +117,7 @@ module LayoutHelper
92 end 117 end
93 118
94 def meta_description_tag(article=nil) 119 def meta_description_tag(article=nil)
95 - article ? truncate(strip_tags(article.body.to_s), :length => 200) : environment.name 120 + article ? CGI.escapeHTML(truncate(strip_tags(article.body.to_s), :length => 200)) : environment.name
96 end 121 end
97 end 122 end
98 123
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 COMMON_CATEGORIES = ActiveSupport::OrderedHash.new 3 COMMON_CATEGORIES = ActiveSupport::OrderedHash.new
4 - COMMON_CATEGORIES[:content] = [:blogs, :image_galleries, :events, :tags] 4 + COMMON_CATEGORIES[:content] = [:blogs, :image_galleries, :events, :article_tags]
5 COMMON_CATEGORIES[:interests] = [:interests] 5 COMMON_CATEGORIES[:interests] = [:interests]
6 COMMON_CATEGORIES[:general] = nil 6 COMMON_CATEGORIES[:general] = nil
7 7
@@ -41,6 +41,8 @@ module ProfileHelper @@ -41,6 +41,8 @@ module ProfileHelper
41 :birth_date => _('Date of birth'), 41 :birth_date => _('Date of birth'),
42 :created_at => _('Profile created at'), 42 :created_at => _('Profile created at'),
43 :members_count => _('Members'), 43 :members_count => _('Members'),
  44 + :privacy_setting => _('Privacy setting'),
  45 + :article_tags => _('Tags')
44 } 46 }
45 47
46 EXCEPTION = { 48 EXCEPTION = {
@@ -63,7 +65,7 @@ module ProfileHelper @@ -63,7 +65,7 @@ module ProfileHelper
63 65
64 def title(field, entry = nil) 66 def title(field, entry = nil)
65 return self.send("#{field}_custom_title", entry) if MULTIPLE[kind].include?(field) && entry.present? 67 return self.send("#{field}_custom_title", entry) if MULTIPLE[kind].include?(field) && entry.present?
66 - CUSTOM_LABELS[field.to_sym] || field.to_s.humanize 68 + CUSTOM_LABELS[field.to_sym] || _(field.to_s.humanize)
67 end 69 end
68 70
69 def display_field(field) 71 def display_field(field)
@@ -73,15 +75,18 @@ module ProfileHelper @@ -73,15 +75,18 @@ module ProfileHelper
73 return '' 75 return ''
74 end 76 end
75 value = begin profile.send(field) rescue nil end 77 value = begin profile.send(field) rescue nil end
76 - p field  
77 - if !value.blank? 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))
  82 + else
78 entries = multiple ? value : [] << value 83 entries = multiple ? value : [] << value
79 entries.map do |entry| 84 entries.map do |entry|
80 content = self.send("treat_#{field}", entry) 85 content = self.send("treat_#{field}", entry)
81 - content_tag('tr', content_tag('td', title(field, entry), :class => 'field-name') + content_tag('td', content)) 86 + unless content.blank?
  87 + content_tag('tr', content_tag('td', title(field, entry), :class => 'field-name') + content_tag('td', content))
  88 + end
82 end.join("\n") 89 end.join("\n")
83 - else  
84 - ''  
85 end 90 end
86 end 91 end
87 92
@@ -98,7 +103,6 @@ module ProfileHelper @@ -98,7 +103,6 @@ module ProfileHelper
98 end 103 end
99 104
100 def treat_date(date) 105 def treat_date(date)
101 - puts date.inspect  
102 show_date(date.to_date) 106 show_date(date.to_date)
103 end 107 end
104 alias :treat_birth_date :treat_date 108 alias :treat_birth_date :treat_date
@@ -133,12 +137,10 @@ module ProfileHelper @@ -133,12 +137,10 @@ module ProfileHelper
133 end 137 end
134 138
135 def treat_blogs(blog) 139 def treat_blogs(blog)
136 - p blog  
137 link_to(n_('One post', '%{num} posts', blog.posts.published.count) % { :num => blog.posts.published.count }, blog.url) 140 link_to(n_('One post', '%{num} posts', blog.posts.published.count) % { :num => blog.posts.published.count }, blog.url)
138 end 141 end
139 142
140 def treat_image_galleries(gallery) 143 def treat_image_galleries(gallery)
141 - p gallery  
142 link_to(n_('One picture', '%{num} pictures', gallery.images.published.count) % { :num => gallery.images.published.count }, gallery.url) 144 link_to(n_('One picture', '%{num} pictures', gallery.images.published.count) % { :num => gallery.images.published.count }, gallery.url)
143 end 145 end
144 146
@@ -146,7 +148,7 @@ module ProfileHelper @@ -146,7 +148,7 @@ module ProfileHelper
146 link_to events.published.count, :controller => 'events', :action => 'events' 148 link_to events.published.count, :controller => 'events', :action => 'events'
147 end 149 end
148 150
149 - def treat_tags(tags) 151 + def treat_article_tags(tags)
150 tag_cloud @tags, :id, { :action => 'tags' }, :max_size => 18, :min_size => 10 152 tag_cloud @tags, :id, { :action => 'tags' }, :max_size => 18, :min_size => 10
151 end 153 end
152 154
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/approve_article.rb
@@ -22,6 +22,7 @@ class ApproveArticle &lt; Task @@ -22,6 +22,7 @@ class ApproveArticle &lt; Task
22 end 22 end
23 23
24 settings_items :closing_statment, :article_parent_id, :highlighted 24 settings_items :closing_statment, :article_parent_id, :highlighted
  25 + settings_items :create_link, :type => :boolean, :default => false
25 26
26 def article_parent 27 def article_parent
27 Article.find_by_id article_parent_id.to_i 28 Article.find_by_id article_parent_id.to_i
@@ -48,7 +49,11 @@ class ApproveArticle &lt; Task @@ -48,7 +49,11 @@ class ApproveArticle &lt; Task
48 end 49 end
49 50
50 def perform 51 def perform
51 - article.copy!(:name => name, :abstract => abstract, :body => body, :profile => target, :reference_article => article, :parent => article_parent, :highlighted => highlighted, :source => article.source, :last_changed_by_id => article.last_changed_by_id, :created_by_id => article.created_by_id) 52 + if create_link
  53 + LinkArticle.create!(:reference_article => article, :profile => target, :parent => article_parent, :highlighted => highlighted)
  54 + else
  55 + article.copy!(:name => name, :abstract => abstract, :body => body, :profile => target, :reference_article => article, :parent => article_parent, :highlighted => highlighted, :source => article.source, :last_changed_by_id => article.last_changed_by_id, :created_by_id => article.created_by_id)
  56 + end
52 end 57 end
53 58
54 def title 59 def title
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
@@ -103,6 +110,11 @@ class Article &lt; ActiveRecord::Base @@ -103,6 +110,11 @@ class Article &lt; ActiveRecord::Base
103 self.activity.destroy if self.activity 110 self.activity.destroy if self.activity
104 end 111 end
105 112
  113 + after_destroy :destroy_link_article
  114 + def destroy_link_article
  115 + Article.where(:reference_article_id => self.id, :type => LinkArticle).destroy_all
  116 + end
  117 +
106 xss_terminate :only => [ :name ], :on => 'validation', :with => 'white_list' 118 xss_terminate :only => [ :name ], :on => 'validation', :with => 'white_list'
107 119
108 scope :in_category, lambda { |category| 120 scope :in_category, lambda { |category|
@@ -285,13 +297,6 @@ class Article &lt; ActiveRecord::Base @@ -285,13 +297,6 @@ class Article &lt; ActiveRecord::Base
285 end 297 end
286 end 298 end
287 299
288 - def reported_version(options = {})  
289 - article = self  
290 - search_path = Rails.root.join('app', 'views', 'shared', 'reported_versions')  
291 - partial_path = File.join('shared', 'reported_versions', partial_for_class_in_view_path(article.class, search_path))  
292 - lambda { render_to_string(:partial => partial_path, :locals => {:article => article}) }  
293 - end  
294 -  
295 # returns the data of the article. Must be overriden in each subclass to 300 # returns the data of the article. Must be overriden in each subclass to
296 # provide the correct content for the article. 301 # provide the correct content for the article.
297 def data 302 def data
@@ -340,7 +345,7 @@ class Article &lt; ActiveRecord::Base @@ -340,7 +345,7 @@ class Article &lt; ActiveRecord::Base
340 def belongs_to_blog? 345 def belongs_to_blog?
341 self.parent and self.parent.blog? 346 self.parent and self.parent.blog?
342 end 347 end
343 - 348 +
344 def belongs_to_forum? 349 def belongs_to_forum?
345 self.parent and self.parent.forum? 350 self.parent and self.parent.forum?
346 end 351 end
@@ -452,6 +457,7 @@ class Article &lt; ActiveRecord::Base @@ -452,6 +457,7 @@ class Article &lt; ActiveRecord::Base
452 if self.parent && !self.parent.published? 457 if self.parent && !self.parent.published?
453 return false 458 return false
454 end 459 end
  460 +
455 true 461 true
456 else 462 else
457 false 463 false
@@ -483,14 +489,17 @@ class Article &lt; ActiveRecord::Base @@ -483,14 +489,17 @@ class Article &lt; ActiveRecord::Base
483 {:conditions => [" articles.published = ? OR 489 {:conditions => [" articles.published = ? OR
484 articles.last_changed_by_id = ? OR 490 articles.last_changed_by_id = ? OR
485 articles.profile_id = ? OR 491 articles.profile_id = ? OR
486 - ?",  
487 - true, user.id, user.id, user.has_permission?(:view_private_content, profile)] } 492 + ? OR articles.show_to_followers = ? AND ?",
  493 + true, user.id, user.id, user.has_permission?(:view_private_content, profile),
  494 + true, user.follows?(profile)]}
488 end 495 end
489 496
  497 +
490 def display_unpublished_article_to?(user) 498 def display_unpublished_article_to?(user)
491 user == author || allow_view_private_content?(user) || user == profile || 499 user == author || allow_view_private_content?(user) || user == profile ||
492 user.is_admin?(profile.environment) || user.is_admin?(profile) || 500 user.is_admin?(profile.environment) || user.is_admin?(profile) ||
493 - article_privacy_exceptions.include?(user) 501 + article_privacy_exceptions.include?(user) ||
  502 + (self.show_to_followers && user.follows?(profile))
494 end 503 end
495 504
496 def display_to?(user = nil) 505 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/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
@@ -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
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_article.rb 0 → 100644
@@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
  1 +class LinkArticle < Article
  2 +
  3 + attr_accessible :reference_article
  4 +
  5 + def self.short_description
  6 + "Article link"
  7 + end
  8 +
  9 + delegate :name, :to => :reference_article
  10 + delegate :body, :to => :reference_article
  11 + delegate :abstract, :to => :reference_article
  12 + delegate :url, :to => :reference_article
  13 +
  14 +end
app/models/link_list_block.rb
@@ -78,8 +78,13 @@ class LinkListBlock &lt; Block @@ -78,8 +78,13 @@ 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
@@ -96,4 +101,5 @@ class LinkListBlock &lt; Block @@ -96,4 +101,5 @@ class LinkListBlock &lt; Block
96 sanitizer = HTML::WhiteListSanitizer.new 101 sanitizer = HTML::WhiteListSanitizer.new
97 sanitizer.sanitize(text) 102 sanitizer.sanitize(text)
98 end 103 end
  104 +
99 end 105 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
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
@@ -97,7 +97,7 @@ class Profile &lt; ActiveRecord::Base @@ -97,7 +97,7 @@ class Profile &lt; ActiveRecord::Base
97 end 97 end
98 98
99 def members_by_name 99 def members_by_name
100 - members.order(:name) 100 + members.order('profiles.name')
101 end 101 end
102 102
103 class << self 103 class << self
@@ -108,8 +108,8 @@ class Profile &lt; ActiveRecord::Base @@ -108,8 +108,8 @@ class Profile &lt; ActiveRecord::Base
108 alias_method_chain :count, :distinct 108 alias_method_chain :count, :distinct
109 end 109 end
110 110
111 - def members_by_role(role)  
112 - Person.members_of(self).all(:conditions => ['role_assignments.role_id = ?', role.id]) 111 + def members_by_role(roles)
  112 + Person.members_of(self).by_role(roles)
113 end 113 end
114 114
115 acts_as_having_boxes 115 acts_as_having_boxes
@@ -121,7 +121,9 @@ class Profile &lt; ActiveRecord::Base @@ -121,7 +121,9 @@ class Profile &lt; ActiveRecord::Base
121 end 121 end
122 122
123 scope :visible, :conditions => { :visible => true } 123 scope :visible, :conditions => { :visible => true }
  124 + scope :disabled, :conditions => { :visible => false }
124 scope :public, :conditions => { :visible => true, :public_profile => true } 125 scope :public, :conditions => { :visible => true, :public_profile => true }
  126 + scope :enabled, :conditions => { :enabled => true }
125 127
126 # Subclasses must override this method 128 # Subclasses must override this method
127 scope :more_popular 129 scope :more_popular
@@ -346,16 +348,17 @@ class Profile &lt; ActiveRecord::Base @@ -346,16 +348,17 @@ class Profile &lt; ActiveRecord::Base
346 end 348 end
347 349
348 def copy_blocks_from(profile) 350 def copy_blocks_from(profile)
  351 + template_boxes = profile.boxes.select{|box| box.position}
349 self.boxes.destroy_all 352 self.boxes.destroy_all
350 - profile.boxes.each do |box|  
351 - new_box = Box.new 353 + self.boxes = template_boxes.size.times.map { Box.new }
  354 +
  355 + template_boxes.each_with_index do |box, i|
  356 + new_box = self.boxes[i]
352 new_box.position = box.position 357 new_box.position = box.position
353 - self.boxes << new_box  
354 box.blocks.each do |block| 358 box.blocks.each do |block|
355 new_block = block.class.new(:title => block[:title]) 359 new_block = block.class.new(:title => block[:title])
356 - new_block.settings = block.settings  
357 - new_block.position = block.position  
358 - self.boxes[-1].blocks << new_block 360 + new_block.copy_from(block)
  361 + new_box.blocks << new_block
359 end 362 end
360 end 363 end
361 end 364 end
@@ -390,7 +393,7 @@ class Profile &lt; ActiveRecord::Base @@ -390,7 +393,7 @@ class Profile &lt; ActiveRecord::Base
390 end 393 end
391 394
392 xss_terminate :only => [ :name, :nickname, :address, :contact_phone, :description ], :on => 'validation' 395 xss_terminate :only => [ :name, :nickname, :address, :contact_phone, :description ], :on => 'validation'
393 - xss_terminate :only => [ :custom_footer, :custom_header ], :with => 'white_list', :on => 'validation' 396 + xss_terminate :only => [ :custom_footer, :custom_header ], :with => 'white_list'
394 397
395 include WhiteListFilter 398 include WhiteListFilter
396 filter_iframes :custom_header, :custom_footer 399 filter_iframes :custom_header, :custom_footer
@@ -774,7 +777,7 @@ private :generate_url, :url_options @@ -774,7 +777,7 @@ private :generate_url, :url_options
774 end 777 end
775 778
776 include Noosfero::Plugin::HotSpot 779 include Noosfero::Plugin::HotSpot
777 - 780 +
778 def folder_types 781 def folder_types
779 types = Article.folder_types 782 types = Article.folder_types
780 plugins.dispatch(:content_types).each {|type| 783 plugins.dispatch(:content_types).each {|type|
@@ -898,6 +901,13 @@ private :generate_url, :url_options @@ -898,6 +901,13 @@ private :generate_url, :url_options
898 end 901 end
899 902
900 def disable 903 def disable
  904 + self.visible = false
  905 + self.save
  906 + end
  907 +
  908 + def enable
  909 + self.visible = true
  910 + self.save
901 end 911 end
902 912
903 def control_panel_settings_button 913 def control_panel_settings_button
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
@@ -201,6 +201,10 @@ class User &lt; ActiveRecord::Base @@ -201,6 +201,10 @@ class User &lt; ActiveRecord::Base
201 Digest::MD5.hexdigest(password) 201 Digest::MD5.hexdigest(password)
202 end 202 end
203 203
  204 + add_encryption_method :salted_md5 do |password, salt|
  205 + Digest::MD5.hexdigest(password+salt)
  206 + end
  207 +
204 add_encryption_method :clear do |password, salt| 208 add_encryption_method :clear do |password, salt|
205 password 209 password
206 end 210 end
@@ -350,6 +354,7 @@ class User &lt; ActiveRecord::Base @@ -350,6 +354,7 @@ class User &lt; ActiveRecord::Base
350 end 354 end
351 355
352 def delay_activation_check 356 def delay_activation_check
  357 + return if person.is_template?
353 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})
354 end 359 end
355 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/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/_link_article.html.erb 0 → 100644
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 +<div>
  2 + <%= labelled_form_field(_('Title'), @article.name) %>
  3 + <%= labelled_form_field(_('Reference'), link_to(url_for @article.view_url)) %>
  4 +
  5 + <%= render :partial => 'general_fields' %>
  6 +</div>
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/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
@@ -27,6 +27,10 @@ @@ -27,6 +27,10 @@
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')))) %> 28 <%= optional_field(@person, 'image', labelled_form_field(_('Image'), file_field(:file, :image, :rel => _('Image')))) %>
29 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 %>
  33 +
30 <% optional_field(@person, 'schooling') do %> 34 <% optional_field(@person, 'schooling') do %>
31 <div class="formfieldline"> 35 <div class="formfieldline">
32 <label class='formlabel' for='profile_data_schooling'><%= _('Schooling') %></label> 36 <label class='formlabel' for='profile_data_schooling'><%= _('Schooling') %></label>
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/profile_actions/xmpp_chat.html.erb
@@ -1,5 +0,0 @@ @@ -1,5 +0,0 @@
1 -<% if profile.members.include?(user) %>  
2 - <li>  
3 - <%= button_to_function(:chat, _('Enter chat room'), "open_chat_window(this, '##{profile.full_jid}')") %>  
4 - </li>  
5 -<% end %>  
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) %>
app/views/shared/tiny_mce.html.erb
1 -<% extend MacrosHelper %>  
2 -<%= javascript_include_tag 'tinymce/jscripts/tiny_mce/tiny_mce.js' %>  
3 -<%= include_macro_js_files %>  
4 -<script type="text/javascript">  
5 - var myplugins = "searchreplace,print,table,contextmenu,-macrosPlugin";  
6 - var first_line, second_line;  
7 - var mode = '<%= mode ||= false %>'  
8 - <% if mode %>  
9 - first_line = "fontsizeselect,bold,italic,underline,bullist,numlist,justifyleft,justifycenter,justifyright,link,unlink"  
10 - second_line = ""  
11 - <% else %>  
12 - first_line = "print,separator,copy,paste,separator,undo,redo,separator,search,replace,separator,forecolor,fontsizeselect,formatselect"  
13 - second_line = "bold,italic,underline,strikethrough,separator,bullist,numlist,separator,justifyleft,justifycenter,justifyright,justifyfull,separator,link,unlink,image,table,separator,cleanup,code,macros"  
14 - <% macros_with_buttons.each do |macro| %>  
15 - second_line += ',<%=macro.identifier %>'  
16 - <% end %>  
17 - <% end %>  
18 -  
19 - if (tinymce.isIE) {  
20 - // the paste plugin is only useful in Internet Explorer  
21 - myplugins = "paste," + myplugins;  
22 - } 1 +<%
  2 +extend TinymceHelper
  3 +mode ||= false
  4 +%>
23 5
  6 +<%= tinymce_js %>
  7 +<script type="text/javascript">
24 tinymce.create('tinymce.plugins.MacrosPlugin', { 8 tinymce.create('tinymce.plugins.MacrosPlugin', {
25 createControl: function(n, cm) { 9 createControl: function(n, cm) {
26 switch (n) { 10 switch (n) {
@@ -49,56 +33,21 @@ tinymce.create(&#39;tinymce.plugins.MacrosPlugin&#39;, { @@ -49,56 +33,21 @@ tinymce.create(&#39;tinymce.plugins.MacrosPlugin&#39;, {
49 } 33 }
50 }); 34 });
51 35
  36 +function tinymce_macros_setup(editor) {
  37 + <% macros_with_buttons.each do |macro| %>
  38 + editor.addButton('<%= macro.identifier %>', {
  39 + title: <%= macro_title(macro).to_json %>,
  40 + onclick: <%= generate_macro_config_dialog(macro) %>,
  41 + image : '<%= macro.configuration[:icon_path]%>'
  42 + });
  43 + <% end %>
  44 +}
  45 +
52 // Register plugin with a short name 46 // Register plugin with a short name
53 tinymce.PluginManager.add('macrosPlugin', tinymce.plugins.MacrosPlugin); 47 tinymce.PluginManager.add('macrosPlugin', tinymce.plugins.MacrosPlugin);
54 48
55 -tinyMCE.init({  
56 - mode : "textareas",  
57 - editor_selector : "mceEditor",  
58 - theme : "advanced",  
59 - relative_urls : false,  
60 - remove_script_host : false,  
61 - document_base_url : <%= environment.top_url.to_json %>,  
62 - plugins: myplugins,  
63 - theme_advanced_toolbar_location : "top",  
64 - theme_advanced_layout_manager: 'SimpleLayout',  
65 - theme_advanced_buttons1 : first_line,  
66 - theme_advanced_buttons2 : second_line,  
67 - theme_advanced_buttons3 : "",  
68 - theme_advanced_blockformats :"p,address,pre,h2,h3,h4,h5,h6",  
69 - paste_auto_cleanup_on_paste : true,  
70 - paste_insert_word_content_callback : "convertWord",  
71 - paste_use_dialog: false,  
72 - apply_source_formatting : true,  
73 - extended_valid_elements : "applet[style|archive|codebase|code|height|width],comment,iframe[src|style|allowtransparency|frameborder|width|height|scrolling],embed[title|src|type|height|width],audio[controls|autoplay],video[controls|autoplay],source[src|type]",  
74 - content_css: '/stylesheets/tinymce.css,<%= macro_css_files %>',  
75 - language: <%= tinymce_language.inspect %>,  
76 - entity_encoding: 'raw',  
77 - setup : function(ed) {  
78 - <% macros_with_buttons.each do |macro| %>  
79 - ed.addButton('<%= macro.identifier %>', {  
80 - title: <%= macro_title(macro).to_json %>,  
81 - onclick: <%= generate_macro_config_dialog(macro) %>,  
82 - image : '<%= macro.configuration[:icon_path]%>'  
83 - });  
84 - <% end %>  
85 - } 49 +jQuery(document).ready(function () {
  50 + <%= tinymce_init_js :mode => mode %>
86 }); 51 });
87 -  
88 -function convertWord(type, content) {  
89 - switch (type) {  
90 - // Gets executed before the built in logic performes it's cleanups  
91 - case "before":  
92 - //content = content.toLowerCase(); // Some dummy logic  
93 - break;  
94 -  
95 - // Gets executed after the built in logic performes it's cleanups  
96 - case "after":  
97 - content = content.replace(/<!--\s*-->/, '');  
98 - break;  
99 - }  
100 -  
101 - return content;  
102 -}  
103 -  
104 </script> 52 </script>
  53 +
app/views/task_mailer/generic_message.text.erb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +<%= _('Dear %s,') % @requestor %>
  2 +
  3 +<%= word_wrap(@message) %>
  4 +
  5 +<%= _('Greetings,') %>
  6 +
  7 +--
  8 +<%= _('%s team.') % @environment %>
  9 +<%= @url %>
app/views/task_mailer/task_activated.text.erb
@@ -1 +0,0 @@ @@ -1 +0,0 @@
1 -task_cancelled.text.erb  
2 \ No newline at end of file 0 \ No newline at end of file
app/views/task_mailer/task_cancelled.text.erb
@@ -1,9 +0,0 @@ @@ -1,9 +0,0 @@
1 -<%= _('Dear %s,') % @requestor %>  
2 -  
3 -<%= word_wrap(@message) %>  
4 -  
5 -<%= _('Greetings,') %>  
6 -  
7 ---  
8 -<%= _('%s team.') % @environment %>  
9 -<%= @url %>  
app/views/task_mailer/task_created.text.erb
@@ -1 +0,0 @@ @@ -1 +0,0 @@
1 -task_cancelled.text.erb  
2 \ No newline at end of file 0 \ No newline at end of file
app/views/task_mailer/task_finished.text.erb
@@ -1 +0,0 @@ @@ -1 +0,0 @@
1 -task_cancelled.text.erb  
2 \ No newline at end of file 0 \ No newline at end of file
app/views/tasks/_approve_article_accept_details.html.erb
1 <%= render :file => 'shared/tiny_mce' %> 1 <%= render :file => 'shared/tiny_mce' %>
2 2
  3 +<%= labelled_form_field(_('Create a link'), f.check_box(:create_link)) %>
  4 +
3 <%= labelled_form_field(_('Name for publishing'), f.text_field(:name)) %> 5 <%= labelled_form_field(_('Name for publishing'), f.text_field(:name)) %>
4 <%= select_profile_folder(_('Select the folder where the article must be published'), "tasks[#{task.id}][task][article_parent_id]", task.target) %> 6 <%= select_profile_folder(_('Select the folder where the article must be published'), "tasks[#{task.id}][task][article_parent_id]", task.target) %>
5 <%= labelled_form_field(_('Highlight this article'), f.check_box(:highlighted)) %> 7 <%= labelled_form_field(_('Highlight this article'), f.check_box(:highlighted)) %>
app/views/templates/index.html.erb
@@ -2,10 +2,11 @@ @@ -2,10 +2,11 @@
2 2
3 <%= _('Manage the templates used on creation of profiles') %> 3 <%= _('Manage the templates used on creation of profiles') %>
4 4
5 -<% list_of_templates = [[_('Person') , environment.people.templates , 'person' ], 5 +<% list_of_templates = [[_('Person') , environment.person_templates , 'person' ],
6 [_('Community') , environment.communities.templates, 'community' ], 6 [_('Community') , environment.communities.templates, 'community' ],
7 [_('Enterprise'), environment.enterprises.templates, 'enterprise']] %> 7 [_('Enterprise'), environment.enterprises.templates, 'enterprise']] %>
8 8
  9 +
9 <% list_of_templates.each do |title, templates, kind|%> 10 <% list_of_templates.each do |title, templates, kind|%>
10 <div class='template-kind'> 11 <div class='template-kind'>
11 <h2><%= title %></h2> 12 <h2><%= title %></h2>
@@ -15,6 +16,11 @@ @@ -15,6 +16,11 @@
15 <li> 16 <li>
16 <%= image_tag "icons-app/#{kind}-icon.png" %> 17 <%= image_tag "icons-app/#{kind}-icon.png" %>
17 <%= link_to(template.name, {:controller => 'profile_editor', :profile => template.identifier}, :title => _('Edit template "%s"') % template.name ) %> 18 <%= link_to(template.name, {:controller => 'profile_editor', :profile => template.identifier}, :title => _('Edit template "%s"') % template.name ) %>
  19 + <% if environment.is_default_template?(template) %>
  20 + <%= _('is the default template') %>
  21 + <% else %>
  22 + <%= link_to(_('Set as default'), {:action => "set_#{kind}_as_default", :template_id => template.id}, :title => _('Set %s template as default') % template.name ) %>
  23 + <% end %>
18 </li> 24 </li>
19 <% end %> 25 <% end %>
20 </ul> 26 </ul>
config/application.rb
@@ -111,9 +111,10 @@ module Noosfero @@ -111,9 +111,10 @@ module Noosfero
111 # Make sure the secret is at least 30 characters and all random, 111 # Make sure the secret is at least 30 characters and all random,
112 # no regular words or you'll be exposed to dictionary attacks. 112 # no regular words or you'll be exposed to dictionary attacks.
113 config.secret_token = noosfero_session_secret 113 config.secret_token = noosfero_session_secret
114 - config.action_dispatch.session = {  
115 - :key => '_noosfero_session',  
116 - } 114 + config.session_store :cookie_store, :key => '_noosfero_session'
  115 +
  116 + config.paths['db/migrate'] += Dir.glob "#{Rails.root}/{baseplugins,config/plugins}/*/db/migrate"
  117 + config.i18n.load_path += Dir.glob "#{Rails.root}/{baseplugins,config/plugins}/*/locales/*.{rb,yml}"
117 118
118 Noosfero::Plugin.setup(config) 119 Noosfero::Plugin.setup(config)
119 120
config/initializers/i18n.rb
1 # necessary for I18n.default_locale to work 1 # necessary for I18n.default_locale to work
2 require 'i18n/backend/fallbacks' 2 require 'i18n/backend/fallbacks'
3 I18n.backend.class.send :include, I18n::Backend::Fallbacks 3 I18n.backend.class.send :include, I18n::Backend::Fallbacks
4 - 4 +I18n.enforce_available_locales = false
config/initializers/noosfero_urls.rb 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +if Rails.env == 'development'
  2 + ActionController::Base.send(:prepend_before_filter) do |controller|
  3 + # XXX note that this is not thread-safe! Accessing a Noosfero instance in
  4 + # development mode under different ports concurrently _will_ lead to weird
  5 + # things happening.
  6 + if [80,443].include?(controller.request.port)
  7 + url_options = {}
  8 + else
  9 + url_options = { :port => controller.request.port }
  10 + end
  11 + Noosfero.instance_variable_set('@development_url_options', url_options)
  12 + end
  13 +end
config/initializers/passenger.rb
@@ -3,7 +3,7 @@ if defined? PhusionPassenger @@ -3,7 +3,7 @@ if defined? PhusionPassenger
3 # from http://russbrooks.com/2010/10/20/rails-cache-memcache-on-passenger-with-smart-spawning 3 # from http://russbrooks.com/2010/10/20/rails-cache-memcache-on-passenger-with-smart-spawning
4 PhusionPassenger.on_event :starting_worker_process do |forked| 4 PhusionPassenger.on_event :starting_worker_process do |forked|
5 if forked 5 if forked
6 - Rails.cache.instance_variable_get(:@data).reset if Rails.cache.class == ActiveSupport::Cache::MemCacheStore 6 + Rails.cache.instance_variable_get(:@data).reset if Rails.cache.class.name == 'ActiveSupport::Cache::MemCacheStore'
7 end 7 end
8 end 8 end
9 end 9 end