Commit 6daf9ba27c9135578f8156e49dfa62f574702d89
Exists in
theme-brasil-digital-from-staging
and in
9 other branches
Merge branch 'master' into rails3-custom_fields
Conflicts: app/helpers/application_helper.rb app/views/profile/_person_profile.html.erb
Showing
1380 changed files
with
86898 additions
and
157983 deletions
Show diff stats
Too many changes.
To preserve performance only 100 of 1380 files displayed.
.ackrc
AUTHORS.md
... | ... | @@ -40,7 +40,9 @@ Alessandro Palmeira + João M. M. Silva <alessandro.palmeira@gmail.com> |
40 | 40 | Alessandro Palmeira + Paulo Meirelles <alessandro.palmeira@gmail.com> |
41 | 41 | Alessandro Palmeira + Paulo Meirelles + João M. M. da Silva <alessandro.palmeira@gmail.com> |
42 | 42 | Alessandro Palmeira + Rafael Manzo <alessandro.palmeira@gmail.com> |
43 | +analosnak <analosnak@gmail.com> | |
43 | 44 | Ana Losnak <analosnak@gmail.com> |
45 | +Andre Bernardes <andrebsguedes@gmail.com> | |
44 | 46 | Antonio Terceiro + Carlos Morais <terceiro@colivre.coop.br> |
45 | 47 | Antonio Terceiro + Paulo Meirelles <terceiro@colivre.coop.br> |
46 | 48 | Antonio Terceiro <terceiro@colivre.coop.br> |
... | ... | @@ -80,7 +82,6 @@ Carlos Morais + Diego Araújo <diegoamc90@gmail.com> |
80 | 82 | Carlos Morais + Eduardo Morais <carlos88morais@gmail.com> |
81 | 83 | Carlos Morais + Paulo Meirelles <carlos88morais@gmail.com> |
82 | 84 | Carlos Morais + Pedro Leal <carlos88morais@gmail.com> |
83 | -Daniela Feitosa <dani@dohko.(none)> | |
84 | 85 | Daniel Alves + Diego Araújo <danpaulalves@gmail.com> |
85 | 86 | Daniel Alves + Diego Araújo <diegoamc90@gmail.com> |
86 | 87 | Daniel Alves + Diego Araújo + Guilherme Rojas <danpaulalves@gmail.com> |
... | ... | @@ -118,7 +119,6 @@ Diego Araújo + Renan Teruo <diegoamc90@gmail.com> |
118 | 119 | Diego Araujo + Rodrigo Souto + Rafael Manzo <rr.manzo@gmail.com> |
119 | 120 | Diego + Jefferson <diegoamc90@gmail.com> |
120 | 121 | Diego Martinez <diegoamc90@gmail.com> |
121 | -Diego Martinez <diego@diego-K55A.(none)> | |
122 | 122 | Diego + Renan <renanteruoc@gmail.com> |
123 | 123 | Eduardo Tourinho Edington <eduardo.edington@serpro.gov.br> |
124 | 124 | Evandro Jr <evandrojr@gmail.com> |
... | ... | @@ -132,6 +132,7 @@ Francisco Marcelo de Araújo Lima Júnior <maljunior@gmail.com> |
132 | 132 | Gabriela Navarro <navarro1703@gmail.com> |
133 | 133 | Grazieno Pellegrino <grazieno@gmail.com> |
134 | 134 | Gust <darksshades@hotmail.com> |
135 | +Hebert Douglas <hebertdougl@gmail.com> | |
135 | 136 | Hugo Melo <hugo@riseup.net> |
136 | 137 | Isaac Canan <isaac@intelletto.com.br> |
137 | 138 | Italo Valcy <italo@dcc.ufba.br> |
... | ... | @@ -193,9 +194,11 @@ Luis David Aguilar Carlos <ludwig9003@gmail.com> |
193 | 194 | Luiz Fernando de Freitas Matos <luiz@luizff.matos@gmail.com> |
194 | 195 | Marcos Ramos <ms.ramos@outlook.com> |
195 | 196 | Martín Olivera <molivera@solar.org.ar> |
197 | +Michal Čihař <michal@cihar.com> | |
196 | 198 | Moises Machado <moises@colivre.coop.br> |
197 | 199 | Naíla Alves <naila@colivre.coop.br> |
198 | 200 | Nanda Lopes <nanda.listas+psl@gmail.com> |
201 | +Parley Martins <parleypachecomartins@gmail.com> | |
199 | 202 | Paulo Meirelles + Alessandro Palmeira + João M. M. da Silva <paulo@softwarelivre.org> |
200 | 203 | Paulo Meirelles + Alessandro Palmeira <paulo@softwarelivre.org> |
201 | 204 | Paulo Meirelles + Carlos Morais <paulo@softwarelivre.org> |
... | ... | @@ -218,6 +221,7 @@ Rafael Reggiani Manzo + João M. M. da Silva <rr.manzo@gmail.com> |
218 | 221 | Rafael Reggiani Manzo <rr.manzo@gmail.com> |
219 | 222 | Raphaël Rousseau <raph@r4f.org> |
220 | 223 | Raquel Lira <raquel.lira@gmail.com> |
224 | +Raquel <rcordioli@gmail.com> | |
221 | 225 | Renan Teruo + Caio Salgado <renanteruoc@gmail.com> |
222 | 226 | Renan Teruoc + Diego Araujo <renanteruoc@gmail.com> |
223 | 227 | Renan Teruo + Diego Araujo <renanteruoc@gmail.com> |
... | ... | @@ -225,11 +229,13 @@ Renan Teruo + Diego Araújo <renanteruoc@gmail.com> |
225 | 229 | Renan Teruo + Paulo Meirelles <renanteruoc@gmail.com> |
226 | 230 | Renan Teruo + Rafael Manzo <renanteruoc@gmail.com> |
227 | 231 | Rodrigo Souto + Ana Losnak + Daniel Bucher + Caio Almeida + Leandro Nunes + Daniela Feitosa + Mariel Zasso <noosfero-br@listas.softwarelivre.org> |
228 | -Rodrigo Souto <diguliu@gmail.com> | |
229 | 232 | Rodrigo Souto <rodrigo@colivre.coop.br> |
230 | 233 | Ronny Kursawe <kursawe.ronny@googlemail.com> |
231 | 234 | root <root@debian.sdr.serpro> |
232 | 235 | Samuel R. C. Vale <srcvale@holoscopio.com> |
236 | +Tallys Martins <tallysmartins@gmail.com> | |
237 | +tallys <tallys@tallys.(none)> | |
238 | +Thiago Zoroastro <thiago.zoroastro@bol.com.br> | |
233 | 239 | Valessio Brito <contato@valessiobrito.com.br> |
234 | 240 | Valessio Brito <contato@valessiobrito.info> |
235 | 241 | Valessio Brito <valessio@gmail.com> | ... | ... |
... | ... | @@ -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. | ... | ... |
Gemfile
1 | 1 | source "https://rubygems.org" |
2 | -gem 'rails' | |
3 | -gem 'fast_gettext' | |
4 | -gem 'acts-as-taggable-on' | |
5 | -gem 'prototype-rails' | |
6 | -gem 'prototype_legacy_helper', '0.0.0', :path => 'vendor/prototype_legacy_helper' | |
7 | -gem 'rails_autolink' | |
8 | -gem 'pg' | |
9 | -gem 'rmagick' | |
10 | -gem 'RedCloth' | |
11 | -gem 'will_paginate' | |
12 | -gem 'ruby-feedparser' | |
13 | -gem 'daemons' | |
14 | -gem 'thin' | |
15 | -gem 'hpricot' | |
16 | -gem 'nokogiri' | |
2 | +gem 'rails', '~> 3.2.19' | |
3 | +gem 'fast_gettext', '~> 0.6.8' | |
4 | +gem 'acts-as-taggable-on', '~> 3.0.2' | |
5 | +gem 'prototype-rails', '~> 3.2.1' | |
6 | +gem 'prototype_legacy_helper', '0.0.0', :path => 'vendor/prototype_legacy_helper' | |
7 | +gem 'rails_autolink', '~> 1.1.5' | |
8 | +gem 'pg', '~> 0.13.2' | |
9 | +gem 'rmagick', '~> 2.13.1' | |
10 | +gem 'RedCloth', '~> 4.2.9' | |
11 | +gem 'will_paginate', '~> 3.0.3' | |
12 | +gem 'ruby-feedparser', '~> 0.7' | |
13 | +gem 'daemons', '~> 1.1.5' | |
14 | +gem 'thin', '~> 1.3.1' | |
15 | +gem 'hpricot', '~> 0.8.6' | |
16 | +gem 'nokogiri', '~> 1.5.5' | |
17 | 17 | gem 'rake', :require => false |
18 | -gem 'rest-client' | |
19 | -gem 'exception_notification' | |
18 | +gem 'rest-client', '~> 1.6.7' | |
19 | +gem 'exception_notification', '~> 4.0.1' | |
20 | +gem 'gettext', '~> 2.2.1', :require => false, :group => :development | |
21 | +gem 'locale', '~> 2.0.5' | |
20 | 22 | |
21 | 23 | # FIXME list here all actual dependencies (i.e. the ones in debian/control), |
22 | 24 | # with their GEM names (not the Debian package names) |
23 | 25 | |
24 | 26 | group :production do |
25 | - gem 'dalli' | |
27 | + gem 'dalli', '~> 2.7.0' | |
26 | 28 | end |
27 | 29 | |
28 | 30 | group :test do |
29 | - gem 'rspec' | |
30 | - gem 'rspec-rails' | |
31 | - gem 'mocha', :require => false | |
31 | + gem 'rspec', '~> 2.10.0' | |
32 | + gem 'rspec-rails', '~> 2.10.1' | |
33 | + gem 'mocha', '~> 1.1.0', :require => false | |
32 | 34 | end |
33 | 35 | |
34 | 36 | group :cucumber do |
35 | - gem 'cucumber-rails', :require => false | |
36 | - gem 'capybara' | |
37 | - gem 'cucumber' | |
38 | - gem 'database_cleaner' | |
39 | - gem 'selenium-webdriver' | |
37 | + gem 'cucumber-rails', '~> 1.0.6', :require => false | |
38 | + gem 'capybara', '~> 2.1.0' | |
39 | + gem 'cucumber', '~> 1.0.6' | |
40 | + gem 'database_cleaner', '~> 1.2.0' | |
41 | + gem 'selenium-webdriver', '~> 2.39.0' | |
40 | 42 | end |
41 | 43 | |
42 | -# include plugin gemfiles | |
43 | -Dir.glob(File.join('config', 'plugins', '*')).each do |plugin| | |
44 | - plugin_gemfile = File.join(plugin, 'Gemfile') | |
45 | - eval File.read(plugin_gemfile) if File.exists?(plugin_gemfile) | |
44 | +# include gemfiles from enabled plugins | |
45 | +# plugins in baseplugins/ are not included on purpose. They should not have any | |
46 | +# dependencies. | |
47 | +Dir.glob('config/plugins/*/Gemfile').each do |gemfile| | |
48 | + eval File.read(gemfile) | |
46 | 49 | end | ... | ... |
Gemfile.lock
... | ... | @@ -1,191 +0,0 @@ |
1 | -PATH | |
2 | - remote: vendor/prototype_legacy_helper | |
3 | - specs: | |
4 | - prototype_legacy_helper (0.0.0) | |
5 | - | |
6 | -GEM | |
7 | - remote: https://rubygems.org/ | |
8 | - specs: | |
9 | - RedCloth (4.2.9) | |
10 | - actionmailer (3.2.6) | |
11 | - actionpack (= 3.2.6) | |
12 | - mail (~> 2.4.4) | |
13 | - actionpack (3.2.6) | |
14 | - activemodel (= 3.2.6) | |
15 | - activesupport (= 3.2.6) | |
16 | - builder (~> 3.0.0) | |
17 | - erubis (~> 2.7.0) | |
18 | - journey (~> 1.0.1) | |
19 | - rack (~> 1.4.0) | |
20 | - rack-cache (~> 1.2) | |
21 | - rack-test (~> 0.6.1) | |
22 | - sprockets (~> 2.1.3) | |
23 | - activemodel (3.2.6) | |
24 | - activesupport (= 3.2.6) | |
25 | - builder (~> 3.0.0) | |
26 | - activerecord (3.2.6) | |
27 | - activemodel (= 3.2.6) | |
28 | - activesupport (= 3.2.6) | |
29 | - arel (~> 3.0.2) | |
30 | - tzinfo (~> 0.3.29) | |
31 | - activeresource (3.2.6) | |
32 | - activemodel (= 3.2.6) | |
33 | - activesupport (= 3.2.6) | |
34 | - activesupport (3.2.6) | |
35 | - i18n (~> 0.6) | |
36 | - multi_json (~> 1.0) | |
37 | - acts-as-taggable-on (3.0.2) | |
38 | - rails (>= 3, < 5) | |
39 | - arel (3.0.2) | |
40 | - builder (3.0.0) | |
41 | - capybara (2.1.0) | |
42 | - mime-types (>= 1.16) | |
43 | - nokogiri (>= 1.3.3) | |
44 | - rack (>= 1.0.0) | |
45 | - rack-test (>= 0.5.4) | |
46 | - xpath (~> 2.0) | |
47 | - childprocess (0.3.3) | |
48 | - ffi (~> 1.0.6) | |
49 | - cucumber (1.0.6) | |
50 | - builder (>= 2.1.2) | |
51 | - diff-lcs (>= 1.1.2) | |
52 | - gherkin (~> 2.4.18) | |
53 | - json (>= 1.4.6) | |
54 | - term-ansicolor (>= 1.0.6) | |
55 | - cucumber-rails (1.0.6) | |
56 | - capybara (>= 1.1.1) | |
57 | - cucumber (>= 1.0.6) | |
58 | - nokogiri (>= 1.5.0) | |
59 | - daemons (1.1.5) | |
60 | - dalli (2.7.0) | |
61 | - database_cleaner (1.2.0) | |
62 | - diff-lcs (1.1.3) | |
63 | - erubis (2.7.0) | |
64 | - eventmachine (0.12.10) | |
65 | - exception_notification (4.0.1) | |
66 | - actionmailer (>= 3.0.4) | |
67 | - activesupport (>= 3.0.4) | |
68 | - fast_gettext (0.6.8) | |
69 | - ffi (1.0.11) | |
70 | - gherkin (2.4.21) | |
71 | - json (>= 1.4.6) | |
72 | - hike (1.2.1) | |
73 | - hpricot (0.8.6) | |
74 | - i18n (0.6.0) | |
75 | - journey (1.0.3) | |
76 | - json (1.7.3) | |
77 | - mail (2.4.4) | |
78 | - i18n (>= 0.4.0) | |
79 | - mime-types (~> 1.16) | |
80 | - treetop (~> 1.4.8) | |
81 | - metaclass (0.0.1) | |
82 | - mime-types (1.19) | |
83 | - mocha (0.11.3) | |
84 | - metaclass (~> 0.0.1) | |
85 | - multi_json (1.3.6) | |
86 | - nokogiri (1.5.5) | |
87 | - pg (0.13.2) | |
88 | - polyglot (0.3.3) | |
89 | - prototype-rails (3.2.1) | |
90 | - rails (~> 3.2) | |
91 | - rack (1.4.1) | |
92 | - rack-cache (1.2) | |
93 | - rack (>= 0.4) | |
94 | - rack-ssl (1.3.2) | |
95 | - rack | |
96 | - rack-test (0.6.1) | |
97 | - rack (>= 1.0) | |
98 | - rails (3.2.6) | |
99 | - actionmailer (= 3.2.6) | |
100 | - actionpack (= 3.2.6) | |
101 | - activerecord (= 3.2.6) | |
102 | - activeresource (= 3.2.6) | |
103 | - activesupport (= 3.2.6) | |
104 | - bundler (~> 1.0) | |
105 | - railties (= 3.2.6) | |
106 | - rails_autolink (1.1.5) | |
107 | - rails (> 3.1) | |
108 | - railties (3.2.6) | |
109 | - actionpack (= 3.2.6) | |
110 | - activesupport (= 3.2.6) | |
111 | - rack-ssl (~> 1.3.2) | |
112 | - rake (>= 0.8.7) | |
113 | - rdoc (~> 3.4) | |
114 | - thor (>= 0.14.6, < 2.0) | |
115 | - rake (0.9.2.2) | |
116 | - rdoc (3.9.4) | |
117 | - rest-client (1.6.7) | |
118 | - mime-types (>= 1.16) | |
119 | - rmagick (2.13.1) | |
120 | - rspec (2.10.0) | |
121 | - rspec-core (~> 2.10.0) | |
122 | - rspec-expectations (~> 2.10.0) | |
123 | - rspec-mocks (~> 2.10.0) | |
124 | - rspec-core (2.10.1) | |
125 | - rspec-expectations (2.10.0) | |
126 | - diff-lcs (~> 1.1.3) | |
127 | - rspec-mocks (2.10.1) | |
128 | - rspec-rails (2.10.1) | |
129 | - actionpack (>= 3.0) | |
130 | - activesupport (>= 3.0) | |
131 | - railties (>= 3.0) | |
132 | - rspec (~> 2.10.0) | |
133 | - ruby-feedparser (0.7) | |
134 | - rubyzip (1.1.2) | |
135 | - selenium-webdriver (2.39.0) | |
136 | - childprocess (>= 0.2.5) | |
137 | - multi_json (~> 1.0) | |
138 | - rubyzip (~> 1.0) | |
139 | - websocket (~> 1.0.4) | |
140 | - sprockets (2.1.3) | |
141 | - hike (~> 1.2) | |
142 | - multi_json (~> 1.0) | |
143 | - rack (~> 1.0) | |
144 | - tilt (~> 1.1, != 1.3.0) | |
145 | - term-ansicolor (1.0.7) | |
146 | - thin (1.3.1) | |
147 | - daemons (>= 1.0.9) | |
148 | - eventmachine (>= 0.12.6) | |
149 | - rack (>= 1.0.0) | |
150 | - thor (0.15.3) | |
151 | - tilt (1.3.3) | |
152 | - treetop (1.4.10) | |
153 | - polyglot | |
154 | - polyglot (>= 0.3.1) | |
155 | - tzinfo (0.3.33) | |
156 | - websocket (1.0.7) | |
157 | - will_paginate (3.0.3) | |
158 | - xpath (2.0.0) | |
159 | - nokogiri (~> 1.3) | |
160 | - | |
161 | -PLATFORMS | |
162 | - ruby | |
163 | - | |
164 | -DEPENDENCIES | |
165 | - RedCloth | |
166 | - acts-as-taggable-on | |
167 | - capybara | |
168 | - cucumber | |
169 | - cucumber-rails | |
170 | - daemons | |
171 | - dalli | |
172 | - database_cleaner | |
173 | - exception_notification | |
174 | - fast_gettext | |
175 | - hpricot | |
176 | - mocha | |
177 | - nokogiri | |
178 | - pg | |
179 | - prototype-rails | |
180 | - prototype_legacy_helper (= 0.0.0)! | |
181 | - rails | |
182 | - rails_autolink | |
183 | - rake | |
184 | - rest-client | |
185 | - rmagick | |
186 | - rspec | |
187 | - rspec-rails | |
188 | - ruby-feedparser | |
189 | - selenium-webdriver | |
190 | - thin | |
191 | - will_paginate |
INSTALL.https.md
1 | -Setup Noosfero to use HTTPS | |
2 | -=========================== | |
1 | +# Setup Noosfero to use HTTPS | |
3 | 2 | |
4 | 3 | This document assumes that you have a fully and clean Noosfero |
5 | 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 | 8 | You should get a valid SSL certificate, but if you want to test |
11 | 9 | your setup before, you could generate a self-signed certificate |
... | ... | @@ -17,99 +15,106 @@ as below: |
17 | 15 | # openssl req -new -x509 -nodes -sha1 -days $[10*365] -key noosfero.key > noosfero.cert |
18 | 16 | # cat noosfero.key noosfero.cert > noosfero.pem |
19 | 17 | |
18 | +## Web server configuration | |
19 | + | |
20 | 20 | There are two ways of using SSL with Noosfero: 1) If you are not using |
21 | 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 | 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 | 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 | 46 | Be aware that if you had configured varnish, the requests won't reach |
47 | 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 | 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 | 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 | 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 | 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 | 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 | +``` | ... | ... |
... | ... | @@ -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 | + | ... | ... |
INSTALL.md
... | ... | @@ -186,8 +186,8 @@ Apache instalation |
186 | 186 | |
187 | 187 | # apt-get install apache2 |
188 | 188 | |
189 | -Apache configuration | |
190 | --------------------- | |
189 | +Configuration - noosfero at / | |
190 | +----------------------------- | |
191 | 191 | |
192 | 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 | 257 | |
258 | 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 | 317 | Enabling exception notifications |
262 | 318 | ================================ | ... | ... |
Rakefile
... | ... | @@ -6,3 +6,13 @@ |
6 | 6 | require File.expand_path('../config/application', __FILE__) |
7 | 7 | |
8 | 8 | Noosfero::Application.load_tasks |
9 | + | |
10 | +[ | |
11 | + "baseplugins/*/{tasks,lib/tasks,rails/tasks}/**/*.rake", | |
12 | + "config/plugins/*/{tasks,lib/tasks,rails/tasks}/**/*.rake", | |
13 | + "config/plugins/*/vendor/plugins/*/{tasks,lib/tasks,rails/tasks}/**/*.rake", | |
14 | +].map do |pattern| | |
15 | + Dir.glob(pattern).sort | |
16 | +end.flatten.each do |taskfile| | |
17 | + load taskfile | |
18 | +end | ... | ... |
Vagrantfile
... | ... | @@ -3,7 +3,7 @@ |
3 | 3 | |
4 | 4 | VAGRANTFILE_API_VERSION = "2" |
5 | 5 | Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| |
6 | - config.vm.box = "debian-wheezy" | |
6 | + config.vm.box = ENV.fetch('VAGRANT_BOX', "debian-wheezy") | |
7 | 7 | config.vm.network :forwarded_port, host: 3000, guest: 3000 |
8 | 8 | config.vm.provision :shell do |shell| |
9 | 9 | shell.inline = 'su vagrant -c /vagrant/script/vagrant' | ... | ... |
app/controllers/admin/admin_panel_controller.rb
... | ... | @@ -71,4 +71,22 @@ class AdminPanelController < AdminController |
71 | 71 | end |
72 | 72 | end |
73 | 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 | 92 | end | ... | ... |
app/controllers/admin/templates_controller.rb
... | ... | @@ -40,8 +40,67 @@ class TemplatesController < AdminController |
40 | 40 | end |
41 | 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 | 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 | 104 | def create_organization_template(klass) |
46 | 105 | identifier = params[:name].to_slug |
47 | 106 | template = klass.new(:name => params[:name], :identifier => identifier, :is_template => true) | ... | ... |
app/controllers/application_controller.rb
... | ... | @@ -40,7 +40,7 @@ class ApplicationController < ActionController::Base |
40 | 40 | |
41 | 41 | theme_layout = theme_option(:layout) |
42 | 42 | if theme_layout |
43 | - theme_view_file('layouts/'+theme_layout) || theme_layout | |
43 | + (theme_view_file('layouts/'+theme_layout) || theme_layout).to_s | |
44 | 44 | else |
45 | 45 | 'application' |
46 | 46 | end |
... | ... | @@ -127,6 +127,9 @@ class ApplicationController < ActionController::Base |
127 | 127 | |
128 | 128 | # TODO: move this logic somewhere else (Domain class?) |
129 | 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 | 133 | @domain = Domain.find_by_name(request.host) |
131 | 134 | if @domain.nil? |
132 | 135 | @environment = Environment.default | ... | ... |
app/controllers/my_profile/cms_controller.rb
... | ... | @@ -174,6 +174,8 @@ class CmsController < MyProfileController |
174 | 174 | |
175 | 175 | post_only :set_home_page |
176 | 176 | def set_home_page |
177 | + return render_access_denied unless user.can_change_homepage? | |
178 | + | |
177 | 179 | article = params[:id].nil? ? nil : profile.articles.find(params[:id]) |
178 | 180 | profile.update_attribute(:home_page, article) |
179 | 181 | |
... | ... | @@ -212,6 +214,7 @@ class CmsController < MyProfileController |
212 | 214 | if @errors.any? |
213 | 215 | render :action => 'upload_files', :parent_id => @parent_id |
214 | 216 | else |
217 | + session[:notice] = _('File(s) successfully uploaded') | |
215 | 218 | if @back_to |
216 | 219 | redirect_to @back_to |
217 | 220 | elsif @parent |
... | ... | @@ -227,7 +230,7 @@ class CmsController < MyProfileController |
227 | 230 | @article = profile.articles.find(params[:id]) |
228 | 231 | if request.post? |
229 | 232 | @article.destroy |
230 | - session[:notice] = _("\"#{@article.name}\" was removed.") | |
233 | + session[:notice] = _("\"%s\" was removed." % @article.name) | |
231 | 234 | referer = Rails.application.routes.recognize_path URI.parse(request.referer).path rescue nil |
232 | 235 | if referer and referer[:controller] == 'cms' and referer[:action] != 'edit' |
233 | 236 | redirect_to referer | ... | ... |
app/controllers/my_profile/profile_design_controller.rb
... | ... | @@ -3,7 +3,16 @@ class ProfileDesignController < BoxOrganizerController |
3 | 3 | needs_profile |
4 | 4 | |
5 | 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 | 16 | def available_blocks |
8 | 17 | blocks = [ ArticleBlock, TagsBlock, RecentDocumentsBlock, ProfileInfoBlock, LinkListBlock, MyNetworkBlock, FeedReaderBlock, ProfileImageBlock, LocationBlock, SlideshowBlock, ProfileSearchBlock, HighlightsBlock ] |
9 | 18 | ... | ... |
app/controllers/my_profile/profile_editor_controller.rb
... | ... | @@ -19,14 +19,16 @@ class ProfileEditorController < MyProfileController |
19 | 19 | params[:profile_data][:custom_fields] ||= {} |
20 | 20 | end |
21 | 21 | Profile.transaction do |
22 | - Image.transaction do | |
23 | - if @profile_data.update_attributes(params[:profile_data]) | |
24 | - redirect_to :action => 'index', :profile => profile.identifier | |
25 | - else | |
26 | - profile.identifier = params[:profile] if profile.identifier.blank? | |
22 | + Image.transaction do | |
23 | + begin | |
24 | + @plugins.dispatch(:profile_editor_transaction_extras) | |
25 | + @profile_data.update_attributes!(params[:profile_data]) | |
26 | + redirect_to :action => 'index', :profile => profile.identifier | |
27 | + rescue Exception => ex | |
28 | + profile.identifier = params[:profile] if profile.identifier.blank? | |
29 | + end | |
27 | 30 | end |
28 | 31 | end |
29 | - end | |
30 | 32 | end |
31 | 33 | end |
32 | 34 | |
... | ... | @@ -75,10 +77,51 @@ class ProfileEditorController < MyProfileController |
75 | 77 | if request.post? |
76 | 78 | if @profile.destroy |
77 | 79 | session[:notice] = _('The profile was deleted.') |
78 | - redirect_to :controller => 'home' | |
80 | + if(params[:return_to]) | |
81 | + redirect_to params[:return_to] | |
82 | + else | |
83 | + redirect_to :controller => 'home' | |
84 | + end | |
79 | 85 | else |
80 | 86 | session[:notice] = _('Could not delete profile') |
81 | 87 | end |
82 | 88 | end |
83 | 89 | end |
90 | + | |
91 | + def deactivate_profile | |
92 | + if environment.admins.include?(current_person) | |
93 | + profile = environment.profiles.find(params[:id]) | |
94 | + if profile.disable | |
95 | + profile.save | |
96 | + session[:notice] = _("The profile '#{profile.name}' was deactivated.") | |
97 | + else | |
98 | + session[:notice] = _('Could not deactivate profile.') | |
99 | + end | |
100 | + end | |
101 | + | |
102 | + redirect_to_previous_location | |
103 | + end | |
104 | + | |
105 | + def activate_profile | |
106 | + if environment.admins.include?(current_person) | |
107 | + profile = environment.profiles.find(params[:id]) | |
108 | + | |
109 | + if profile.enable | |
110 | + session[:notice] = _("The profile '#{profile.name}' was activated.") | |
111 | + else | |
112 | + session[:notice] = _('Could not activate the profile.') | |
113 | + end | |
114 | + end | |
115 | + | |
116 | + redirect_to_previous_location | |
117 | + end | |
118 | + | |
119 | + protected | |
120 | + | |
121 | + def redirect_to_previous_location | |
122 | + back = request.referer | |
123 | + back = "/" if back.nil? | |
124 | + | |
125 | + redirect_to back | |
126 | + end | |
84 | 127 | end | ... | ... |
app/controllers/my_profile/profile_members_controller.rb
... | ... | @@ -20,7 +20,7 @@ class ProfileMembersController < MyProfileController |
20 | 20 | redirect_to :action => :last_admin |
21 | 21 | elsif @person.define_roles(@roles, profile) |
22 | 22 | session[:notice] = _('Roles successfuly updated') |
23 | - redirect_to :controller => 'profile_editor' | |
23 | + redirect_to :action => 'index' | |
24 | 24 | else |
25 | 25 | session[:notice] = _('Couldn\'t change the roles') |
26 | 26 | redirect_to :action => 'index' | ... | ... |
app/controllers/public/account_controller.rb
... | ... | @@ -104,6 +104,7 @@ class AccountController < ApplicationController |
104 | 104 | @user.return_to = session[:return_to] |
105 | 105 | @person = Person.new(params[:profile_data]) |
106 | 106 | @person.environment = @user.environment |
107 | + | |
107 | 108 | if request.post? |
108 | 109 | if may_be_a_bot |
109 | 110 | set_signup_start_time_for_now |
... | ... | @@ -122,6 +123,14 @@ class AccountController < ApplicationController |
122 | 123 | invitation.update_attributes!({:friend => @user.person}) |
123 | 124 | invitation.finish |
124 | 125 | end |
126 | + | |
127 | + unless params[:file].nil? | |
128 | + image = Image::new :uploaded_data=> params[:file][:image] | |
129 | + | |
130 | + @user.person.image = image | |
131 | + @user.person.save | |
132 | + end | |
133 | + | |
125 | 134 | if @user.activated? |
126 | 135 | self.current_user = @user |
127 | 136 | check_join_in_community(@user) |
... | ... | @@ -191,7 +200,7 @@ class AccountController < ApplicationController |
191 | 200 | else |
192 | 201 | @change_password.errors[:base] << _('Could not find any user with %s equal to "%s".') % [fields_label, params[:value]] |
193 | 202 | end |
194 | - rescue ActiveRecord::RecordInvald | |
203 | + rescue ActiveRecord::RecordInvalid | |
195 | 204 | @change_password.errors[:base] << _('Could not perform password recovery for the user.') |
196 | 205 | end |
197 | 206 | end | ... | ... |
app/controllers/public/chat_controller.rb
... | ... | @@ -19,9 +19,13 @@ class ChatController < PublicController |
19 | 19 | def avatar |
20 | 20 | profile = environment.profiles.find_by_identifier(params[:id]) |
21 | 21 | filename, mimetype = profile_icon(profile, :minor, true) |
22 | - data = File.read(File.join(Rails.root, 'public', filename)) | |
23 | - render :text => data, :layout => false, :content_type => mimetype | |
24 | - expires_in 24.hours | |
22 | + if filename =~ /^(https?:)?\/\// | |
23 | + redirect_to filename | |
24 | + else | |
25 | + data = File.read(File.join(Rails.root, 'public', filename)) | |
26 | + render :text => data, :layout => false, :content_type => mimetype | |
27 | + expires_in 24.hours | |
28 | + end | |
25 | 29 | end |
26 | 30 | |
27 | 31 | def index | ... | ... |
app/controllers/public/contact_controller.rb
1 | 1 | class ContactController < PublicController |
2 | 2 | |
3 | - before_filter :login_required | |
4 | - | |
5 | 3 | needs_profile |
6 | 4 | |
7 | 5 | def new |
8 | - @contact | |
6 | + @contact = build_contact | |
9 | 7 | if request.post? && params[:confirm] == 'true' |
10 | - @contact = user.build_contact(profile, params[:contact]) | |
11 | 8 | @contact.city = (!params[:city].blank? && City.exists?(params[:city])) ? City.find(params[:city]).name : nil |
12 | 9 | @contact.state = (!params[:state].blank? && State.exists?(params[:state])) ? State.find(params[:state]).name : nil |
13 | 10 | if @contact.deliver |
... | ... | @@ -16,8 +13,17 @@ class ContactController < PublicController |
16 | 13 | else |
17 | 14 | session[:notice] = _('Contact not sent') |
18 | 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 | 25 | else |
20 | - @contact = user.build_contact(profile) | |
26 | + Contact.new params[:contact].merge(dest: profile) | |
21 | 27 | end |
22 | 28 | end |
23 | 29 | ... | ... |
app/controllers/public/content_viewer_controller.rb
... | ... | @@ -126,7 +126,7 @@ class ContentViewerController < ApplicationController |
126 | 126 | elsif !@page.display_to?(user) |
127 | 127 | if !profile.public? |
128 | 128 | private_profile_partial_parameters |
129 | - render :template => 'profile/_private_profile', :status => 403 | |
129 | + render :template => 'profile/_private_profile', :status => 403, :formats => [:html] | |
130 | 130 | allowed = false |
131 | 131 | else #if !profile.visible? |
132 | 132 | render_access_denied |
... | ... | @@ -216,8 +216,6 @@ class ContentViewerController < ApplicationController |
216 | 216 | if @page.has_posts? |
217 | 217 | posts = get_posts(params[:year], params[:month]) |
218 | 218 | |
219 | - posts = posts.includes(:parent, {:profile => [:domains, :environment]}, :author) | |
220 | - | |
221 | 219 | #FIXME Need to run this before the pagination because this version of |
222 | 220 | # will_paginate returns a will_paginate collection instead of a |
223 | 221 | # relation. | ... | ... |
app/controllers/public/profile_controller.rb
... | ... | @@ -17,7 +17,11 @@ class ProfileController < PublicController |
17 | 17 | end |
18 | 18 | @tags = profile.article_tags |
19 | 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 | 25 | end |
22 | 26 | end |
23 | 27 | |
... | ... | @@ -61,13 +65,13 @@ class ProfileController < PublicController |
61 | 65 | |
62 | 66 | def friends |
63 | 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 | 69 | end |
66 | 70 | end |
67 | 71 | |
68 | 72 | def members |
69 | 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 | 75 | end |
72 | 76 | end |
73 | 77 | |
... | ... | @@ -315,7 +319,7 @@ class ProfileController < PublicController |
315 | 319 | abuse_report = AbuseReport.new(params[:abuse_report]) |
316 | 320 | if !params[:content_type].blank? |
317 | 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 | 323 | end |
320 | 324 | |
321 | 325 | user.register_report(abuse_report, profile) |
... | ... | @@ -394,6 +398,7 @@ class ProfileController < PublicController |
394 | 398 | |
395 | 399 | def private_profile |
396 | 400 | private_profile_partial_parameters |
401 | + render :action => 'index', :status => 403 | |
397 | 402 | end |
398 | 403 | |
399 | 404 | def invisible_profile | ... | ... |
app/controllers/public/search_controller.rb
... | ... | @@ -90,10 +90,14 @@ class SearchController < PublicController |
90 | 90 | end |
91 | 91 | |
92 | 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 | 101 | date_range = (@date - 1.month).at_beginning_of_month..(@date + 1.month).at_end_of_month |
98 | 102 | |
99 | 103 | @events = [] | ... | ... |
app/helpers/application_helper.rb
... | ... | @@ -304,7 +304,7 @@ module ApplicationHelper |
304 | 304 | def partial_for_class(klass, prefix=nil, suffix=nil) |
305 | 305 | raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' if klass.nil? |
306 | 306 | name = klass.name.underscore |
307 | - controller.view_paths.reverse_each do |view_path| | |
307 | + controller.view_paths.each do |view_path| | |
308 | 308 | partial = partial_for_class_in_view_path(klass, view_path, prefix, suffix) |
309 | 309 | return partial if partial |
310 | 310 | end |
... | ... | @@ -433,19 +433,19 @@ module ApplicationHelper |
433 | 433 | end |
434 | 434 | |
435 | 435 | def theme_site_title |
436 | - theme_include('site_title') | |
436 | + @theme_site_title ||= theme_include 'site_title' | |
437 | 437 | end |
438 | 438 | |
439 | 439 | def theme_header |
440 | - theme_include('header') | |
440 | + @theme_header ||= theme_include 'header' | |
441 | 441 | end |
442 | 442 | |
443 | 443 | def theme_footer |
444 | - theme_include('footer') | |
444 | + @theme_footer ||= theme_include 'footer' | |
445 | 445 | end |
446 | 446 | |
447 | 447 | def theme_extra_navigation |
448 | - theme_include('navigation') | |
448 | + @theme_extra_navigation ||= theme_include 'navigation' | |
449 | 449 | end |
450 | 450 | |
451 | 451 | def is_testing_theme |
... | ... | @@ -482,7 +482,12 @@ module ApplicationHelper |
482 | 482 | '/images/icons-app/enterprise-'+ size.to_s() +'.png' |
483 | 483 | end |
484 | 484 | else |
485 | - '/images/icons-app/person-'+ size.to_s() +'.png' | |
485 | + pixels = Image.attachment_options[:thumbnails][size].split('x').first | |
486 | + gravatar_profile_image_url( | |
487 | + profile.email, | |
488 | + :size => pixels, | |
489 | + :d => gravatar_default | |
490 | + ) | |
486 | 491 | end |
487 | 492 | filename = default_or_themed_icon(icon) |
488 | 493 | end |
... | ... | @@ -602,7 +607,7 @@ module ApplicationHelper |
602 | 607 | end |
603 | 608 | |
604 | 609 | def gravatar_default |
605 | - (respond_to?(:theme_option) && theme_option.present? && theme_option['gravatar']) || NOOSFERO_CONF['gravatar'] | |
610 | + (respond_to?(:theme_option) && theme_option.present? && theme_option['gravatar']) || NOOSFERO_CONF['gravatar'] || 'mm' | |
606 | 611 | end |
607 | 612 | |
608 | 613 | attr_reader :environment |
... | ... | @@ -669,13 +674,14 @@ module ApplicationHelper |
669 | 674 | html.join "\n" |
670 | 675 | end |
671 | 676 | |
677 | + def theme_javascript_src | |
678 | + script = File.join theme_path, 'theme.js' | |
679 | + script if File.exists? File.join(Rails.root, 'public', script) | |
680 | + end | |
681 | + | |
672 | 682 | def theme_javascript_ng |
673 | - script = File.join(theme_path, 'theme.js') | |
674 | - if File.exists?(File.join(Rails.root, 'public', script)) | |
675 | - javascript_include_tag script | |
676 | - else | |
677 | - nil | |
678 | - end | |
683 | + script = theme_javascript_src | |
684 | + javascript_include_tag script if script | |
679 | 685 | end |
680 | 686 | |
681 | 687 | def file_field_or_thumbnail(label, image, i) |
... | ... | @@ -856,8 +862,9 @@ module ApplicationHelper |
856 | 862 | end |
857 | 863 | |
858 | 864 | def base_url |
859 | - environment.top_url | |
865 | + environment.top_url(request.scheme) | |
860 | 866 | end |
867 | + alias :top_url :base_url | |
861 | 868 | |
862 | 869 | def helper_for_article(article) |
863 | 870 | article_helper = ActionView::Base.new |
... | ... | @@ -902,13 +909,15 @@ module ApplicationHelper |
902 | 909 | end |
903 | 910 | |
904 | 911 | def page_title |
905 | - (@page ? @page.title + ' - ' : '') + | |
906 | - (@topic ? @topic.title + ' - ' : '') + | |
907 | - (@section ? @section.title + ' - ' : '') + | |
908 | - (@toc ? _('Online Manual') + ' - ' : '') + | |
909 | - (controller.controller_name == 'chat' ? _('Chat') + ' - ' : '') + | |
910 | - (profile ? profile.short_name : environment.name) + | |
911 | - (@category ? " - #{@category.full_name}" : '') | |
912 | + CGI.escapeHTML( | |
913 | + (@page ? @page.title + ' - ' : '') + | |
914 | + (@topic ? @topic.title + ' - ' : '') + | |
915 | + (@section ? @section.title + ' - ' : '') + | |
916 | + (@toc ? _('Online Manual') + ' - ' : '') + | |
917 | + (controller.controller_name == 'chat' ? _('Chat') + ' - ' : '') + | |
918 | + (profile ? profile.short_name : environment.name) + | |
919 | + (@category ? " - #{@category.full_name}" : '') | |
920 | + ) | |
912 | 921 | end |
913 | 922 | |
914 | 923 | # DEPRECATED. Do not use this. |
... | ... | @@ -937,9 +946,9 @@ module ApplicationHelper |
937 | 946 | # from Article model for an ArticleBlock. |
938 | 947 | def reference_to_article(text, article, anchor=nil) |
939 | 948 | if article.profile.domains.empty? |
940 | - href = "/#{article.url[:profile]}/" | |
949 | + href = "#{Noosfero.root}/#{article.url[:profile]}/" | |
941 | 950 | else |
942 | - href = "http://#{article.profile.domains.first.name}/" | |
951 | + href = "http://#{article.profile.domains.first.name}#{Noosfero.root}/" | |
943 | 952 | end |
944 | 953 | href += article.url[:page].join('/') |
945 | 954 | href += '#' + anchor if anchor |
... | ... | @@ -1280,11 +1289,13 @@ module ApplicationHelper |
1280 | 1289 | end |
1281 | 1290 | |
1282 | 1291 | def delete_article_message(article) |
1283 | - if article.folder? | |
1284 | - _("Are you sure that you want to remove the folder \"#{article.name}\"? Note that all the items inside it will also be removed!") | |
1285 | - else | |
1286 | - _("Are you sure that you want to remove the item \"#{article.name}\"?") | |
1287 | - end | |
1292 | + CGI.escapeHTML( | |
1293 | + if article.folder? | |
1294 | + _("Are you sure that you want to remove the folder \"%s\"? Note that all the items inside it will also be removed!") % article.name | |
1295 | + else | |
1296 | + _("Are you sure that you want to remove the item \"%s\"?") % article.name | |
1297 | + end | |
1298 | + ) | |
1288 | 1299 | end |
1289 | 1300 | |
1290 | 1301 | def expirable_link_to(expired, content, url, options = {}) |
... | ... | @@ -1301,7 +1312,7 @@ module ApplicationHelper |
1301 | 1312 | end |
1302 | 1313 | |
1303 | 1314 | def template_options(kind, field_name) |
1304 | - templates = environment.send(kind).templates.order('name') | |
1315 | + templates = environment.send(kind).templates | |
1305 | 1316 | return '' if templates.count == 0 |
1306 | 1317 | if templates.count == 1 |
1307 | 1318 | if templates.first.custom_fields == {} |
... | ... | @@ -1315,10 +1326,16 @@ module ApplicationHelper |
1315 | 1326 | content_tag('div', custom_fields) |
1316 | 1327 | end |
1317 | 1328 | else |
1318 | - options = options_for_select(templates.collect{ |template| [template.name, template.id]}) | |
1319 | - content_tag('div', | |
1320 | - content_tag('div', content_tag('label', _('Profile organization'), :class => 'formlabel') + (select_tag 'profile_data[template_id]', options, :onchange => 'show_fields_for_template(this);')), | |
1321 | - :id => 'template-options') | |
1329 | + radios = templates.map do |template| | |
1330 | + content_tag('li', labelled_radio_button(link_to(template.name, template.url, :target => '_blank'), "#{field_name}[template_id]", template.id, environment.is_default_template?(template))) | |
1331 | + end.join("\n") | |
1332 | + | |
1333 | + content_tag('div', content_tag('label', _('Profile organization'), :for => 'template-options', :class => 'formlabel') + | |
1334 | + content_tag('p', _('Your profile will be created according to the selected template. Click on the options to view them.'), :style => 'margin: 5px 15px;padding: 0px 10px;') + | |
1335 | + content_tag('ul', radios, :style => 'list-style: none; padding-left: 20px; margin-top: 0.5em;'), | |
1336 | + :id => 'template-options', | |
1337 | + :style => 'margin-top: 1em' | |
1338 | + ) | |
1322 | 1339 | end |
1323 | 1340 | end |
1324 | 1341 | |
... | ... | @@ -1375,7 +1392,7 @@ module ApplicationHelper |
1375 | 1392 | # are old things that do not support it we are keeping this hot spot. |
1376 | 1393 | html = @plugins.pipeline(:parse_content, html, source).first |
1377 | 1394 | end |
1378 | - html | |
1395 | + html && html.html_safe | |
1379 | 1396 | end |
1380 | 1397 | |
1381 | 1398 | def convert_macro(html, source) | ... | ... |
app/helpers/article_helper.rb
... | ... | @@ -3,6 +3,12 @@ module ArticleHelper |
3 | 3 | include PrototypeHelper |
4 | 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 | 12 | def custom_options_for_article(article, tokenized_children) |
7 | 13 | @article = article |
8 | 14 | |
... | ... | @@ -71,12 +77,59 @@ module ArticleHelper |
71 | 77 | content_tag('div', |
72 | 78 | radio_button(:article, :published, false) + |
73 | 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 | 133 | end |
81 | 134 | |
82 | 135 | def prepare_to_token_input(array) | ... | ... |
app/helpers/boxes_helper.rb
... | ... | @@ -170,49 +170,54 @@ module BoxesHelper |
170 | 170 | else |
171 | 171 | "before-block-#{block.id}" |
172 | 172 | end |
173 | - | |
174 | - content_tag('div', ' ', :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', ' ', :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 | 178 | end |
176 | 179 | |
177 | 180 | # makes the given block draggable so it can be moved away. |
178 | 181 | def block_handle(block) |
179 | - draggable_element("block-#{block.id}", :revert => true) | |
182 | + modifiable?(block) ? draggable_element("block-#{block.id}", :revert => true) : "" | |
180 | 183 | end |
181 | 184 | |
182 | 185 | def block_edit_buttons(block) |
183 | 186 | buttons = [] |
184 | 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 | 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 | 221 | end |
217 | 222 | |
218 | 223 | if block.respond_to?(:help) |
... | ... | @@ -248,5 +253,7 @@ module BoxesHelper |
248 | 253 | classes |
249 | 254 | end |
250 | 255 | |
251 | - | |
256 | + def modifiable?(block) | |
257 | + return !block.fixed || environment.admins.include?(user) | |
258 | + end | |
252 | 259 | end | ... | ... |
app/helpers/content_viewer_helper.rb
... | ... | @@ -10,7 +10,7 @@ module ContentViewerHelper |
10 | 10 | end |
11 | 11 | |
12 | 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 | 14 | end |
15 | 15 | |
16 | 16 | def article_title(article, args = {}) |
... | ... | @@ -45,7 +45,7 @@ module ContentViewerHelper |
45 | 45 | { article.environment.locales[translation.language] => { :href => url_for(translation.url) } } |
46 | 46 | end |
47 | 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 | 49 | :class => 'article-translations-menu simplemenu-trigger up'), |
50 | 50 | :class => 'article-translations') |
51 | 51 | end | ... | ... |
app/helpers/layout_helper.rb
... | ... | @@ -2,12 +2,31 @@ module LayoutHelper |
2 | 2 | |
3 | 3 | def body_classes |
4 | 4 | # Identify the current controller and action for the CSS: |
5 | + (logged_in? ? " logged-in" : "") + | |
5 | 6 | " controller-#{controller.controller_name}" + |
6 | 7 | " action-#{controller.controller_name}-#{controller.action_name}" + |
7 | 8 | " template-#{@layout_template || if profile.blank? then 'default' else profile.layout_template end}" + |
8 | 9 | (!profile.nil? && profile.is_on_homepage?(request.path,@page) ? " profile-homepage" : "") |
9 | 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 | 30 | def noosfero_javascript |
12 | 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 | 36 | unless plugins_javascripts.empty? |
18 | 37 | output += javascript_include_tag plugins_javascripts, :cache => "cache/plugins-#{Digest::MD5.hexdigest plugins_javascripts.to_s}" |
19 | 38 | end |
39 | + output += theme_javascript_ng.to_s | |
40 | + | |
20 | 41 | output |
21 | 42 | end |
22 | 43 | |
... | ... | @@ -84,6 +105,10 @@ module LayoutHelper |
84 | 105 | theme_path + '/style.css' |
85 | 106 | end |
86 | 107 | |
108 | + def layout_template | |
109 | + if profile then profile.layout_template else environment.layout_template end | |
110 | + end | |
111 | + | |
87 | 112 | def addthis_javascript |
88 | 113 | if NOOSFERO_CONF['addthis_enabled'] |
89 | 114 | '<script src="https://s7.addthis.com/js/152/addthis_widget.js"></script>' |
... | ... | @@ -91,7 +116,7 @@ module LayoutHelper |
91 | 116 | end |
92 | 117 | |
93 | 118 | def meta_description_tag(article=nil) |
94 | - article ? truncate(strip_tags(article.body.to_s), :length => 200) : environment.name | |
119 | + article ? CGI.escapeHTML(truncate(strip_tags(article.body.to_s), :length => 200)) : environment.name | |
95 | 120 | end |
96 | 121 | end |
97 | 122 | ... | ... |
app/helpers/person_notifier_helper.rb
app/helpers/profile_helper.rb
1 | 1 | module ProfileHelper |
2 | 2 | |
3 | - def display_field(title, profile, field, force = false) | |
3 | + COMMON_CATEGORIES = ActiveSupport::OrderedHash.new | |
4 | + COMMON_CATEGORIES[:content] = [:blogs, :image_galleries, :events, :article_tags] | |
5 | + COMMON_CATEGORIES[:interests] = [:interests] | |
6 | + COMMON_CATEGORIES[:general] = nil | |
7 | + | |
8 | + PERSON_CATEGORIES = ActiveSupport::OrderedHash.new | |
9 | + PERSON_CATEGORIES[:basic_information] = [:nickname, :sex, :birth_date, :location, :privacy_setting, :created_at] | |
10 | + PERSON_CATEGORIES[:contact] = [:contact_phone, :cell_phone, :comercial_phone, :contact_information, :email, :personal_website, :jabber_id] | |
11 | + PERSON_CATEGORIES[:location] = [:address, :address_reference, :zip_code, :city, :state, :district, :country, :nationality] | |
12 | + PERSON_CATEGORIES[:work] = [:organization, :organization_website, :professional_activity] | |
13 | + PERSON_CATEGORIES[:study] = [:schooling, :formation, :area_of_study] | |
14 | + PERSON_CATEGORIES[:network] = [:friends, :communities, :enterprises] | |
15 | + PERSON_CATEGORIES.merge!(COMMON_CATEGORIES) | |
16 | + | |
17 | + ORGANIZATION_CATEGORIES = ActiveSupport::OrderedHash.new | |
18 | + ORGANIZATION_CATEGORIES[:basic_information] = [:display_name, :created_at, :foundation_year, :type, :language, :members_count, :location, :address_reference, :historic_and_current_context, :admins] | |
19 | + ORGANIZATION_CATEGORIES[:contact] = [:contact_person, :contact_phone, :contact_email, :organization_website, :jabber_id] | |
20 | + ORGANIZATION_CATEGORIES[:economic] = [:business_name, :acronym, :economic_activity, :legal_form, :products, :activities_short_description, :management_information] | |
21 | + ORGANIZATION_CATEGORIES.merge!(COMMON_CATEGORIES) | |
22 | + | |
23 | + CATEGORY_MAP = ActiveSupport::OrderedHash.new | |
24 | + CATEGORY_MAP[:person] = PERSON_CATEGORIES | |
25 | + CATEGORY_MAP[:organization] = ORGANIZATION_CATEGORIES | |
26 | + | |
27 | + FORCE = { | |
28 | + :person => [:privacy_setting], | |
29 | + :organization => [:privacy_setting, :location], | |
30 | + } | |
31 | + | |
32 | + MULTIPLE = { | |
33 | + :person => [:blogs, :image_galleries, :interests], | |
34 | + :organization => [:blogs, :image_galleries, :interests], | |
35 | + } | |
36 | + | |
37 | + CUSTOM_LABELS = { | |
38 | + :zip_code => _('ZIP code'), | |
39 | + :email => _('e-Mail'), | |
40 | + :jabber_id => _('Jabber'), | |
41 | + :birth_date => _('Date of birth'), | |
42 | + :created_at => _('Profile created at'), | |
43 | + :members_count => _('Members'), | |
44 | + :privacy_setting => _('Privacy setting'), | |
45 | + :article_tags => _('Tags') | |
46 | + } | |
47 | + | |
48 | + EXCEPTION = { | |
49 | + :person => [:image, :preferred_domain, :description, :tag_list], | |
50 | + :organization => [:image, :preferred_domain, :description, :tag_list, :address, :zip_code, :city, :state, :country, :district] | |
51 | + } | |
52 | + | |
53 | + def general_fields | |
54 | + categorized_fields = CATEGORY_MAP[kind].values.flatten | |
55 | + profile.class.fields.map(&:to_sym) - categorized_fields - EXCEPTION[kind] | |
56 | + end | |
57 | + | |
58 | + def kind | |
59 | + if profile.kind_of?(Person) | |
60 | + :person | |
61 | + else | |
62 | + :organization | |
63 | + end | |
64 | + end | |
65 | + | |
66 | + def title(field, entry = nil) | |
67 | + return self.send("#{field}_custom_title", entry) if MULTIPLE[kind].include?(field) && entry.present? | |
68 | + CUSTOM_LABELS[field.to_sym] || _(field.to_s.humanize) | |
69 | + end | |
70 | + | |
71 | + def display_field(field) | |
72 | + force = FORCE[kind].include?(field) | |
73 | + multiple = MULTIPLE[kind].include?(field) | |
4 | 74 | unless force || profile.may_display_field_to?(field, user) |
5 | 75 | return '' |
6 | 76 | end |
7 | - value = profile.send(field) | |
8 | - if !value.blank? | |
9 | - if block_given? | |
10 | - value = yield(value) | |
11 | - end | |
12 | - content_tag('tr', content_tag('td', title, :class => 'field-name') + content_tag('td', value)) | |
77 | + value = begin profile.send(field) rescue nil end | |
78 | + return '' if value.blank? | |
79 | + if value.kind_of?(Hash) | |
80 | + content = self.send("treat_#{field}", value) | |
81 | + content_tag('tr', content_tag('td', title(field), :class => 'field-name') + content_tag('td', content)) | |
13 | 82 | else |
14 | - '' | |
83 | + entries = multiple ? value : [] << value | |
84 | + entries.map do |entry| | |
85 | + content = self.send("treat_#{field}", entry) | |
86 | + unless content.blank? | |
87 | + content_tag('tr', content_tag('td', title(field, entry), :class => 'field-name') + content_tag('td', content)) | |
88 | + end | |
89 | + end.join("\n") | |
15 | 90 | end |
16 | 91 | end |
17 | 92 | |
18 | - def display_contact(profile) | |
19 | - fields = [] | |
20 | - fields << display_field(_('Address:'), profile, :address).html_safe | |
21 | - fields << display_field(_('ZIP code:'), profile, :zip_code).html_safe | |
22 | - fields << display_field(_('Contact phone:'), profile, :contact_phone).html_safe | |
23 | - fields << display_field(_('e-Mail:'), profile, :email) { |email| link_to_email(email) }.html_safe | |
24 | - fields << display_field(_('Personal website:'), profile, :personal_website).html_safe | |
25 | - fields << display_field(_('Jabber:'), profile, :jabber_id).html_safe | |
26 | - if fields.reject!(&:blank?).empty? | |
27 | - '' | |
28 | - else | |
29 | - content_tag('tr', content_tag('th', _('Contact'), { :colspan => 2 })) + fields.join.html_safe | |
93 | + def treat_email(email) | |
94 | + link_to_email(email) | |
95 | + end | |
96 | + | |
97 | + def treat_organization_website(url) | |
98 | + link_to(url, url) | |
99 | + end | |
100 | + | |
101 | + def treat_sex(gender) | |
102 | + { 'male' => _('Male'), 'female' => _('Female') }[gender] | |
103 | + end | |
104 | + | |
105 | + def treat_date(date) | |
106 | + show_date(date.to_date) | |
107 | + end | |
108 | + alias :treat_birth_date :treat_date | |
109 | + alias :treat_created_at :treat_date | |
110 | + | |
111 | + def treat_friends(friends) | |
112 | + link_to friends.count, :controller => 'profile', :action => 'friends' | |
113 | + end | |
114 | + | |
115 | + def treat_communities(communities) | |
116 | + link_to communities.count, :controller => "profile", :action => 'communities' | |
117 | + end | |
118 | + | |
119 | + def treat_enterprises(enterprises) | |
120 | + if environment.disabled?('disable_asset_enterprises') | |
121 | + link_to enterprises.count, :controller => "profile", :action => 'enterprises' | |
122 | + end | |
123 | + end | |
124 | + | |
125 | + def treat_members_count(count) | |
126 | + link_to count, :controller => 'profile', :action => 'members' | |
127 | + end | |
128 | + | |
129 | + def treat_products(products) | |
130 | + if profile.kind_of?(Enterprise) && profile.environment.enabled?('products_for_enterprises') | |
131 | + link_to _('Products/Services'), :controller => 'catalog', :action => 'index' | |
30 | 132 | end |
31 | 133 | end |
32 | 134 | |
33 | - def display_work_info(profile) | |
34 | - organization = display_field(_('Organization:'), profile, :organization) | |
35 | - organization_site = display_field(_('Organization website:'), profile, :organization_website) { |url| link_to(url, url) } | |
36 | - if organization.blank? && organization_site.blank? | |
37 | - '' | |
135 | + def treat_admins(admins) | |
136 | + profile.admins.map { |admin| link_to(admin.short_name, admin.url)}.join(', ') | |
137 | + end | |
138 | + | |
139 | + def treat_blogs(blog) | |
140 | + link_to(n_('One post', '%{num} posts', blog.posts.published.count) % { :num => blog.posts.published.count }, blog.url) | |
141 | + end | |
142 | + | |
143 | + def treat_image_galleries(gallery) | |
144 | + link_to(n_('One picture', '%{num} pictures', gallery.images.published.count) % { :num => gallery.images.published.count }, gallery.url) | |
145 | + end | |
146 | + | |
147 | + def treat_events(events) | |
148 | + link_to events.published.count, :controller => 'events', :action => 'events' | |
149 | + end | |
150 | + | |
151 | + def treat_article_tags(tags) | |
152 | + tag_cloud @tags, :id, { :action => 'tags' }, :max_size => 18, :min_size => 10 | |
153 | + end | |
154 | + | |
155 | + def treat_interests(interest) | |
156 | + link_to interest.name, :controller => 'search', :action => 'category_index', :category_path => interest.explode_path | |
157 | + end | |
158 | + | |
159 | + def article_custom_title(article) | |
160 | + article.name | |
161 | + end | |
162 | + alias :blogs_custom_title :article_custom_title | |
163 | + alias :image_galleries_custom_title :article_custom_title | |
164 | + | |
165 | + def interests_custom_title(interest) | |
166 | + '' | |
167 | + end | |
168 | + | |
169 | + def method_missing(method, *args, &block) | |
170 | + if method.to_s =~ /^treat_(.+)$/ | |
171 | + args[0] | |
172 | + elsif method.to_s =~ /^display_(.+)$/ && CATEGORY_MAP[kind].has_key?($1.to_sym) | |
173 | + category = $1.to_sym | |
174 | + fields = category == :general ? general_fields : CATEGORY_MAP[kind][category] | |
175 | + contents = [] | |
176 | + | |
177 | + fields.each do |field| | |
178 | + contents << display_field(field).html_safe | |
179 | + end | |
180 | + | |
181 | + contents = contents.delete_if(&:blank?) | |
182 | + | |
183 | + unless contents.empty? | |
184 | + content_tag('tr', content_tag('th', title(category), { :colspan => 2 })) + contents.join.html_safe | |
185 | + else | |
186 | + '' | |
187 | + end | |
38 | 188 | else |
39 | - content_tag('tr', content_tag('th', _('Work'), { :colspan => 2 })) + organization + organization_site | |
189 | + super | |
40 | 190 | end |
41 | 191 | end |
42 | 192 | ... | ... |
app/helpers/role_helper.rb
app/helpers/search_helper.rb
... | ... | @@ -21,6 +21,12 @@ module SearchHelper |
21 | 21 | 'more_comments' => _('More comments') |
22 | 22 | } |
23 | 23 | |
24 | + COMMON_PROFILE_LIST_BLOCK = [ | |
25 | + :enterprises, | |
26 | + :people, | |
27 | + :communities | |
28 | + ] | |
29 | + | |
24 | 30 | # FIXME remove it after search_controler refactored |
25 | 31 | include EventsHelper |
26 | 32 | |
... | ... | @@ -94,7 +100,7 @@ module SearchHelper |
94 | 100 | compact_link = display?(asset, :compact) ? (display == 'compact' ? _('Compact') : link_to(_('Compact'), params.merge(:display => 'compact'))) : nil |
95 | 101 | map_link = display?(asset, :map) ? (display == 'map' ? _('Map') : link_to(_('Map'), params.merge(:display => 'map'))) : nil |
96 | 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 | 104 | content_tag('strong', _('Display')) + ': ' + [compact_link, map_link, full_link].compact.join(' | ').html_safe, |
99 | 105 | :class => 'search-customize-options' |
100 | 106 | ) | ... | ... |
app/helpers/sweeper_helper.rb
... | ... | @@ -56,12 +56,12 @@ module SweeperHelper |
56 | 56 | if profile |
57 | 57 | profile.blocks.each {|block| |
58 | 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 | 61 | end |
62 | 62 | environment.blocks.each {|block| |
63 | 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 | 67 | blocks_to_expire.uniq! | ... | ... |
... | ... | @@ -0,0 +1,51 @@ |
1 | +module TinymceHelper | |
2 | + include MacrosHelper | |
3 | + | |
4 | + def tinymce_js | |
5 | + output = '' | |
6 | + output += javascript_include_tag 'tinymce/js/tinymce/tinymce.min.js' | |
7 | + output += javascript_include_tag 'tinymce/js/tinymce/jquery.tinymce.min.js' | |
8 | + output += javascript_include_tag 'tinymce.js' | |
9 | + output += include_macro_js_files.to_s | |
10 | + output | |
11 | + end | |
12 | + | |
13 | + def tinymce_init_js options = {} | |
14 | + options.merge! :document_base_url => top_url, | |
15 | + :content_css => "/stylesheets/tinymce.css,#{macro_css_files}", | |
16 | + :plugins => %w[compat3x advlist autolink lists link image charmap print preview hr anchor pagebreak | |
17 | + searchreplace wordcount visualblocks visualchars code fullscreen | |
18 | + insertdatetime media nonbreaking save table contextmenu directionality | |
19 | + emoticons template paste textcolor colorpicker textpattern], | |
20 | + :language => tinymce_language | |
21 | + | |
22 | + options[:toolbar1] = "insertfile undo redo | copy paste | bold italic underline | styleselect fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image" | |
23 | + if options[:mode] == 'simple' | |
24 | + options[:menubar] = false | |
25 | + else | |
26 | + options[:menubar] = 'edit insert view tools' | |
27 | + options[:toolbar2] = 'print preview code media | table' | |
28 | + | |
29 | + options[:toolbar2] += ' | macros' | |
30 | + macros_with_buttons.each do |macro| | |
31 | + options[:toolbar2] += " #{macro.identifier}" | |
32 | + end | |
33 | + end | |
34 | + | |
35 | + options[:macros_setup] = macros_with_buttons.map do |macro| | |
36 | + <<-EOS | |
37 | + ed.addButton('#{macro.identifier}', { | |
38 | + title: #{macro_title(macro).to_json}, | |
39 | + onclick: #{generate_macro_config_dialog macro}, | |
40 | + image : '#{macro.configuration[:icon_path]}' | |
41 | + }); | |
42 | + EOS | |
43 | + end | |
44 | + | |
45 | + #cleanup non tinymce options | |
46 | + options = options.except :mode | |
47 | + | |
48 | + "noosfero.tinymce.init(#{options.to_json})" | |
49 | + end | |
50 | + | |
51 | +end | ... | ... |
app/models/article.rb
... | ... | @@ -2,7 +2,14 @@ require 'hpricot' |
2 | 2 | |
3 | 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 | 14 | acts_as_having_image |
8 | 15 | |
... | ... | @@ -157,14 +164,17 @@ class Article < ActiveRecord::Base |
157 | 164 | self.profile |
158 | 165 | end |
159 | 166 | |
160 | - def self.human_attribute_name(attrib, options = {}) | |
167 | + def self.human_attribute_name_with_customization(attrib, options={}) | |
161 | 168 | case attrib.to_sym |
162 | 169 | when :name |
163 | 170 | _('Title') |
164 | 171 | else |
165 | - _(self.superclass.human_attribute_name(attrib)) | |
172 | + _(self.human_attribute_name_without_customization(attrib)) | |
166 | 173 | end |
167 | 174 | end |
175 | + class << self | |
176 | + alias_method_chain :human_attribute_name, :customization | |
177 | + end | |
168 | 178 | |
169 | 179 | def css_class_list |
170 | 180 | [self.class.name.to_css_class] |
... | ... | @@ -282,13 +292,6 @@ class Article < ActiveRecord::Base |
282 | 292 | end |
283 | 293 | end |
284 | 294 | |
285 | - def reported_version(options = {}) | |
286 | - article = self | |
287 | - search_path = Rails.root.join('app', 'views', 'shared', 'reported_versions') | |
288 | - partial_path = File.join('shared', 'reported_versions', partial_for_class_in_view_path(article.class, search_path)) | |
289 | - lambda { render_to_string(:partial => partial_path, :locals => {:article => article}) } | |
290 | - end | |
291 | - | |
292 | 295 | # returns the data of the article. Must be overriden in each subclass to |
293 | 296 | # provide the correct content for the article. |
294 | 297 | def data |
... | ... | @@ -337,7 +340,7 @@ class Article < ActiveRecord::Base |
337 | 340 | def belongs_to_blog? |
338 | 341 | self.parent and self.parent.blog? |
339 | 342 | end |
340 | - | |
343 | + | |
341 | 344 | def belongs_to_forum? |
342 | 345 | self.parent and self.parent.forum? |
343 | 346 | end |
... | ... | @@ -449,6 +452,7 @@ class Article < ActiveRecord::Base |
449 | 452 | if self.parent && !self.parent.published? |
450 | 453 | return false |
451 | 454 | end |
455 | + | |
452 | 456 | true |
453 | 457 | else |
454 | 458 | false |
... | ... | @@ -480,14 +484,17 @@ class Article < ActiveRecord::Base |
480 | 484 | {:conditions => [" articles.published = ? OR |
481 | 485 | articles.last_changed_by_id = ? OR |
482 | 486 | articles.profile_id = ? OR |
483 | - ?", | |
484 | - true, user.id, user.id, user.has_permission?(:view_private_content, profile)] } | |
487 | + ? OR articles.show_to_followers = ? AND ?", | |
488 | + true, user.id, user.id, user.has_permission?(:view_private_content, profile), | |
489 | + true, user.follows?(profile)]} | |
485 | 490 | end |
486 | 491 | |
492 | + | |
487 | 493 | def display_unpublished_article_to?(user) |
488 | 494 | user == author || allow_view_private_content?(user) || user == profile || |
489 | 495 | user.is_admin?(profile.environment) || user.is_admin?(profile) || |
490 | - article_privacy_exceptions.include?(user) | |
496 | + article_privacy_exceptions.include?(user) || | |
497 | + (self.show_to_followers && user.follows?(profile)) | |
491 | 498 | end |
492 | 499 | |
493 | 500 | def display_to?(user = nil) | ... | ... |
app/models/block.rb
1 | 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 | 5 | # to be able to generate HTML |
6 | 6 | include ActionView::Helpers::UrlHelper |
... | ... | @@ -64,7 +64,7 @@ class Block < ActiveRecord::Base |
64 | 64 | end |
65 | 65 | |
66 | 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 | 68 | end |
69 | 69 | |
70 | 70 | def display_always(context) |
... | ... | @@ -75,7 +75,7 @@ class Block < ActiveRecord::Base |
75 | 75 | if context[:article] |
76 | 76 | return context[:article] == owner.home_page |
77 | 77 | else |
78 | - return context[:request_path] == '/' | |
78 | + return home_page_path?(context[:request_path]) | |
79 | 79 | end |
80 | 80 | end |
81 | 81 | |
... | ... | @@ -83,7 +83,7 @@ class Block < ActiveRecord::Base |
83 | 83 | if context[:article] |
84 | 84 | return context[:article] != owner.home_page |
85 | 85 | else |
86 | - return context[:request_path] != '/' + (owner.kind_of?(Profile) ? owner.identifier : '') | |
86 | + return !home_page_path?(context[:request_path]) | |
87 | 87 | end |
88 | 88 | end |
89 | 89 | |
... | ... | @@ -110,11 +110,14 @@ class Block < ActiveRecord::Base |
110 | 110 | # * <tt>'all'</tt>: the block is always displayed |
111 | 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 | 116 | # returns the description of the block, used when the user sees a list of |
114 | 117 | # blocks to choose one to include in the design. |
115 | 118 | # |
116 | 119 | # Must be redefined in subclasses to match the description of each block |
117 | - # type. | |
120 | + # type. | |
118 | 121 | def self.description |
119 | 122 | '(dummy)' |
120 | 123 | end |
... | ... | @@ -124,13 +127,13 @@ class Block < ActiveRecord::Base |
124 | 127 | # This method can return several types of objects: |
125 | 128 | # |
126 | 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 | 131 | # * <tt>Proc</tt>: the Proc is evaluated in the scope of BoxesHelper. The |
129 | 132 | # block can then use <tt>render</tt>, <tt>link_to</tt>, etc. |
130 | 133 | # |
131 | 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 | 137 | def content(args={}) |
135 | 138 | "This is block number %d" % self.id |
136 | 139 | end |
... | ... | @@ -192,7 +195,7 @@ class Block < ActiveRecord::Base |
192 | 195 | |
193 | 196 | # Override in your subclasses. |
194 | 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 | 199 | # Possible contexts are: :profile, :environment |
197 | 200 | def self.expire_on |
198 | 201 | { |
... | ... | @@ -221,6 +224,7 @@ class Block < ActiveRecord::Base |
221 | 224 | 'all' => _('All users'), |
222 | 225 | 'logged' => _('Logged'), |
223 | 226 | 'not_logged' => _('Not logged'), |
227 | + 'followers' => owner.class != Environment && owner.organization? ? _('Members') : _('Friends') | |
224 | 228 | } |
225 | 229 | end |
226 | 230 | |
... | ... | @@ -234,4 +238,26 @@ class Block < ActiveRecord::Base |
234 | 238 | duplicated_block |
235 | 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 | 263 | end | ... | ... |
app/models/blog.rb
... | ... | @@ -53,7 +53,7 @@ class Blog < Folder |
53 | 53 | def prepare_external_feed |
54 | 54 | unless self.external_feed_data.nil? |
55 | 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 | 57 | else |
58 | 58 | self.build_external_feed(self.external_feed_data, :without_protection => true) |
59 | 59 | end | ... | ... |
app/models/change_password.rb
... | ... | @@ -2,16 +2,19 @@ class ChangePassword < Task |
2 | 2 | |
3 | 3 | attr_accessor :password, :password_confirmation |
4 | 4 | |
5 | - def self.human_attribute_name(attrib, options = {}) | |
5 | + def self.human_attribute_name_with_customization(attrib, options={}) | |
6 | 6 | case attrib.to_sym |
7 | 7 | when :password |
8 | 8 | _('Password') |
9 | 9 | when :password_confirmation |
10 | 10 | _('Password Confirmation') |
11 | 11 | else |
12 | - _(self.superclass.human_attribute_name(attrib)) | |
12 | + _(self.human_attribute_name_without_customization(attrib)) | |
13 | 13 | end |
14 | 14 | end |
15 | + class << self | |
16 | + alias_method_chain :human_attribute_name, :customization | |
17 | + end | |
15 | 18 | |
16 | 19 | validates_presence_of :requestor |
17 | 20 | ... | ... |
app/models/community.rb
... | ... | @@ -50,16 +50,6 @@ class Community < Organization |
50 | 50 | super + FIELDS |
51 | 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 | 53 | def active_fields |
64 | 54 | environment ? environment.active_community_fields : [] |
65 | 55 | end |
... | ... | @@ -78,7 +68,7 @@ class Community < Organization |
78 | 68 | end |
79 | 69 | |
80 | 70 | def default_template |
81 | - environment.community_template | |
71 | + environment.community_default_template | |
82 | 72 | end |
83 | 73 | |
84 | 74 | def news(limit = 30, highlight = false) | ... | ... |
app/models/domain.rb
... | ... | @@ -92,4 +92,11 @@ class Domain < ActiveRecord::Base |
92 | 92 | @hosting = {} |
93 | 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 | 102 | end | ... | ... |
app/models/enterprise.rb
... | ... | @@ -59,16 +59,6 @@ class Enterprise < Organization |
59 | 59 | super + FIELDS |
60 | 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 | 62 | def active_fields |
73 | 63 | environment ? environment.active_enterprise_fields : [] |
74 | 64 | end |
... | ... | @@ -107,7 +97,12 @@ class Enterprise < Organization |
107 | 97 | self.tasks.where(:type => 'EnterpriseActivation').first |
108 | 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 | 106 | return if enabled |
112 | 107 | # must be set first for the following to work |
113 | 108 | self.enabled = true |
... | ... | @@ -169,7 +164,7 @@ class Enterprise < Organization |
169 | 164 | end |
170 | 165 | |
171 | 166 | def default_template |
172 | - environment.enterprise_template | |
167 | + environment.enterprise_default_template | |
173 | 168 | end |
174 | 169 | |
175 | 170 | def template_with_inactive_enterprise | ... | ... |
app/models/environment.rb
... | ... | @@ -283,6 +283,7 @@ class Environment < ActiveRecord::Base |
283 | 283 | www.flickr.com |
284 | 284 | www.gmodules.com |
285 | 285 | www.youtube.com |
286 | + openstreetmap.org | |
286 | 287 | ] + ('a' .. 'z').map{|i| "#{i}.yimg.com"} |
287 | 288 | |
288 | 289 | settings_items :enabled_plugins, :type => Array, :default => Noosfero::Plugin.available_plugin_names |
... | ... | @@ -656,10 +657,11 @@ class Environment < ActiveRecord::Base |
656 | 657 | { :controller => 'admin_panel', :action => 'index' } |
657 | 658 | end |
658 | 659 | |
659 | - def top_url | |
660 | - url = 'http://' | |
660 | + def top_url(scheme = 'http') | |
661 | + url = scheme + '://' | |
661 | 662 | url << (Noosfero.url_options.key?(:host) ? Noosfero.url_options[:host] : default_hostname) |
662 | 663 | url << ':' << Noosfero.url_options[:port].to_s if Noosfero.url_options.key?(:port) |
664 | + url << Noosfero.root('') | |
663 | 665 | url |
664 | 666 | end |
665 | 667 | |
... | ... | @@ -727,31 +729,50 @@ class Environment < ActiveRecord::Base |
727 | 729 | ] |
728 | 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 | 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 | 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 | 754 | end |
738 | 755 | |
739 | - def person_template | |
756 | + def person_default_template | |
740 | 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 | 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 | 767 | end |
747 | 768 | |
748 | - def enterprise_template | |
769 | + def enterprise_default_template | |
749 | 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 | 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 | 776 | end |
756 | 777 | |
757 | 778 | def inactive_enterprise_template |
... | ... | @@ -804,7 +825,7 @@ class Environment < ActiveRecord::Base |
804 | 825 | end |
805 | 826 | |
806 | 827 | def notification_emails |
807 | - [noreply_email.blank? ? nil : noreply_email].compact + admins.map(&:email) | |
828 | + [contact_email].select(&:present?) + admins.map(&:email) | |
808 | 829 | end |
809 | 830 | |
810 | 831 | after_create :create_templates |
... | ... | @@ -849,10 +870,10 @@ class Environment < ActiveRecord::Base |
849 | 870 | person_template.visible = false |
850 | 871 | person_template.save! |
851 | 872 | |
852 | - self.enterprise_template = enterprise_template | |
873 | + self.enterprise_default_template = enterprise_template | |
853 | 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 | 877 | self.save! |
857 | 878 | end |
858 | 879 | |
... | ... | @@ -916,6 +937,10 @@ class Environment < ActiveRecord::Base |
916 | 937 | locales_list |
917 | 938 | end |
918 | 939 | |
940 | + def has_license? | |
941 | + self.licenses.any? | |
942 | + end | |
943 | + | |
919 | 944 | private |
920 | 945 | |
921 | 946 | def default_language_available | ... | ... |
app/models/event.rb
... | ... | @@ -19,7 +19,7 @@ class Event < Article |
19 | 19 | maybe_add_http(self.setting[:link]) |
20 | 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 | 24 | def initialize(*args) |
25 | 25 | super(*args) | ... | ... |
app/models/external_feed.rb
... | ... | @@ -10,9 +10,10 @@ class ExternalFeed < ActiveRecord::Base |
10 | 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 | 15 | def add_item(title, link, date, content) |
16 | + return if content.blank? | |
16 | 17 | doc = Hpricot(content) |
17 | 18 | doc.search('*').each do |p| |
18 | 19 | if p.instance_of? Hpricot::Elem |
... | ... | @@ -30,6 +31,7 @@ class ExternalFeed < ActiveRecord::Base |
30 | 31 | article.source = link |
31 | 32 | article.profile = blog.profile |
32 | 33 | article.parent = blog |
34 | + article.author_name = self.feed_title | |
33 | 35 | unless blog.children.exists?(:slug => article.slug) |
34 | 36 | article.save! |
35 | 37 | article.delay.create_activity | ... | ... |
app/models/feed_reader_block.rb
app/models/folder.rb
... | ... | @@ -12,7 +12,7 @@ class Folder < Article |
12 | 12 | |
13 | 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 | 17 | include WhiteListFilter |
18 | 18 | filter_iframes :body | ... | ... |
app/models/invitation.rb
... | ... | @@ -65,18 +65,16 @@ class Invitation < Task |
65 | 65 | |
66 | 66 | task_args = if user.nil? |
67 | 67 | {:person => person, :friend_name => friend_name, :friend_email => friend_email, :message => message} |
68 | - elsif !user.person.is_a_friend?(person) | |
68 | + else | |
69 | 69 | {:person => person, :target => user.person} |
70 | 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 | 78 | end |
81 | 79 | end |
82 | 80 | end | ... | ... |
app/models/link_list_block.rb
... | ... | @@ -78,16 +78,17 @@ class LinkListBlock < Block |
78 | 78 | address |
79 | 79 | end |
80 | 80 | if add !~ /^[a-z]+:\/\// && add !~ /^\// |
81 | - 'http://' + add | |
81 | + '//' + add | |
82 | 82 | else |
83 | + if root = Noosfero.root | |
84 | + if !add.starts_with?(root) | |
85 | + add = root + add | |
86 | + end | |
87 | + end | |
83 | 88 | add |
84 | 89 | end |
85 | 90 | end |
86 | 91 | |
87 | - def editable? | |
88 | - true | |
89 | - end | |
90 | - | |
91 | 92 | def icons_options |
92 | 93 | ICONS.map do |i| |
93 | 94 | "<span title=\"#{i[1]}\" class=\"icon-#{i[0]}\" onclick=\"changeIcon(this, '#{i[0]}')\"></span>".html_safe |
... | ... | @@ -100,4 +101,5 @@ class LinkListBlock < Block |
100 | 101 | sanitizer = HTML::WhiteListSanitizer.new |
101 | 102 | sanitizer.sanitize(text) |
102 | 103 | end |
104 | + | |
103 | 105 | end | ... | ... |
app/models/main_block.rb
app/models/organization.rb
... | ... | @@ -30,6 +30,16 @@ class Organization < Profile |
30 | 30 | |
31 | 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 | 43 | def validation_methodology |
34 | 44 | self.validation_info ? self.validation_info.validation_methodology : nil |
35 | 45 | end |
... | ... | @@ -135,7 +145,11 @@ class Organization < Profile |
135 | 145 | end |
136 | 146 | |
137 | 147 | def notification_emails |
138 | - [contact_email.blank? ? nil : contact_email].compact + admins.map(&:email) | |
148 | + emails = [contact_email].select(&:present?) + admins.map(&:email) | |
149 | + if emails.empty? | |
150 | + emails << environment.contact_email | |
151 | + end | |
152 | + emails | |
139 | 153 | end |
140 | 154 | |
141 | 155 | def already_request_membership?(person) | ... | ... |
app/models/person.rb
... | ... | @@ -21,6 +21,12 @@ class Person < Profile |
21 | 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 | 30 | def has_permission_with_plugins?(permission, profile) |
25 | 31 | permissions = [has_permission_without_plugins?(permission, profile)] |
26 | 32 | permissions += plugins.map do |plugin| |
... | ... | @@ -74,6 +80,10 @@ class Person < Profile |
74 | 80 | |
75 | 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 | 87 | def can_control_scrap?(scrap) |
78 | 88 | begin |
79 | 89 | !self.scraps(scrap).nil? |
... | ... | @@ -161,7 +171,7 @@ class Person < Profile |
161 | 171 | FIELDS |
162 | 172 | end |
163 | 173 | |
164 | - validate :presence_of_required_fields | |
174 | + validate :presence_of_required_fields, :unless => :is_template | |
165 | 175 | |
166 | 176 | def presence_of_required_fields |
167 | 177 | self.required_fields.each do |field| |
... | ... | @@ -300,7 +310,7 @@ class Person < Profile |
300 | 310 | end |
301 | 311 | |
302 | 312 | def default_template |
303 | - environment.person_template | |
313 | + environment.person_default_template | |
304 | 314 | end |
305 | 315 | |
306 | 316 | def apply_type_specific_template(template) | ... | ... |
app/models/person_notifier.rb
app/models/product.rb
... | ... | @@ -11,7 +11,7 @@ class Product < ActiveRecord::Base |
11 | 11 | |
12 | 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 | 16 | def self.default_search_display |
17 | 17 | 'full' | ... | ... |
app/models/profile.rb
... | ... | @@ -125,7 +125,7 @@ class Profile < ActiveRecord::Base |
125 | 125 | end |
126 | 126 | |
127 | 127 | def members_by_name |
128 | - members.order(:name) | |
128 | + members.order('profiles.name') | |
129 | 129 | end |
130 | 130 | |
131 | 131 | class << self |
... | ... | @@ -136,8 +136,8 @@ class Profile < ActiveRecord::Base |
136 | 136 | alias_method_chain :count, :distinct |
137 | 137 | end |
138 | 138 | |
139 | - def members_by_role(role) | |
140 | - Person.members_of(self).all(:conditions => ['role_assignments.role_id = ?', role.id]) | |
139 | + def members_by_role(roles) | |
140 | + Person.members_of(self).by_role(roles) | |
141 | 141 | end |
142 | 142 | |
143 | 143 | acts_as_having_boxes |
... | ... | @@ -149,7 +149,9 @@ class Profile < ActiveRecord::Base |
149 | 149 | end |
150 | 150 | |
151 | 151 | scope :visible, :conditions => { :visible => true } |
152 | + scope :disabled, :conditions => { :visible => false } | |
152 | 153 | scope :public, :conditions => { :visible => true, :public_profile => true } |
154 | + scope :enabled, :conditions => { :enabled => true } | |
153 | 155 | |
154 | 156 | # Subclasses must override this method |
155 | 157 | scope :more_popular |
... | ... | @@ -374,16 +376,17 @@ class Profile < ActiveRecord::Base |
374 | 376 | end |
375 | 377 | |
376 | 378 | def copy_blocks_from(profile) |
379 | + template_boxes = profile.boxes.select{|box| box.position} | |
377 | 380 | self.boxes.destroy_all |
378 | - profile.boxes.each do |box| | |
379 | - new_box = Box.new | |
381 | + self.boxes = template_boxes.size.times.map { Box.new } | |
382 | + | |
383 | + template_boxes.each_with_index do |box, i| | |
384 | + new_box = self.boxes[i] | |
380 | 385 | new_box.position = box.position |
381 | - self.boxes << new_box | |
382 | 386 | box.blocks.each do |block| |
383 | 387 | new_block = block.class.new(:title => block[:title]) |
384 | - new_block.settings = block.settings | |
385 | - new_block.position = block.position | |
386 | - self.boxes[-1].blocks << new_block | |
388 | + new_block.copy_from(block) | |
389 | + new_box.blocks << new_block | |
387 | 390 | end |
388 | 391 | end |
389 | 392 | end |
... | ... | @@ -418,7 +421,7 @@ class Profile < ActiveRecord::Base |
418 | 421 | end |
419 | 422 | |
420 | 423 | xss_terminate :only => [ :name, :nickname, :address, :contact_phone, :description ], :on => 'validation' |
421 | - xss_terminate :only => [ :custom_footer, :custom_header ], :with => 'white_list', :on => 'validation' | |
424 | + xss_terminate :only => [ :custom_footer, :custom_header ], :with => 'white_list' | |
422 | 425 | |
423 | 426 | include WhiteListFilter |
424 | 427 | filter_iframes :custom_header, :custom_footer |
... | ... | @@ -802,7 +805,7 @@ private :generate_url, :url_options |
802 | 805 | end |
803 | 806 | |
804 | 807 | include Noosfero::Plugin::HotSpot |
805 | - | |
808 | + | |
806 | 809 | def folder_types |
807 | 810 | types = Article.folder_types |
808 | 811 | plugins.dispatch(:content_types).each {|type| |
... | ... | @@ -926,6 +929,13 @@ private :generate_url, :url_options |
926 | 929 | end |
927 | 930 | |
928 | 931 | def disable |
932 | + self.visible = false | |
933 | + self.save | |
934 | + end | |
935 | + | |
936 | + def enable | |
937 | + self.visible = true | |
938 | + self.save | |
929 | 939 | end |
930 | 940 | |
931 | 941 | def control_panel_settings_button | ... | ... |
app/models/profile_image_block.rb
app/models/profile_info_block.rb
app/models/profile_search_block.rb
app/models/task.rb
... | ... | @@ -285,8 +285,9 @@ class Task < ActiveRecord::Base |
285 | 285 | # If |
286 | 286 | def send_notification(action) |
287 | 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 | 291 | end |
291 | 292 | end |
292 | 293 | end | ... | ... |
app/models/user.rb
... | ... | @@ -16,15 +16,18 @@ class User < ActiveRecord::Base |
16 | 16 | end |
17 | 17 | |
18 | 18 | # FIXME ugly workaround |
19 | - def self.human_attribute_name(attrib, options={}) | |
19 | + def self.human_attribute_name_with_customization(attrib, options={}) | |
20 | 20 | case attrib.to_sym |
21 | 21 | when :login |
22 | 22 | return [_('Username'), _('Email')].join(' / ') |
23 | 23 | when :email |
24 | 24 | return _('e-Mail') |
25 | - else _(self.superclass.human_attribute_name(attrib)) | |
25 | + else _(self.human_attribute_name_without_customization(attrib)) | |
26 | 26 | end |
27 | 27 | end |
28 | + class << self | |
29 | + alias_method_chain :human_attribute_name, :customization | |
30 | + end | |
28 | 31 | |
29 | 32 | before_create do |user| |
30 | 33 | if user.environment.nil? |
... | ... | @@ -198,6 +201,10 @@ class User < ActiveRecord::Base |
198 | 201 | Digest::MD5.hexdigest(password) |
199 | 202 | end |
200 | 203 | |
204 | + add_encryption_method :salted_md5 do |password, salt| | |
205 | + Digest::MD5.hexdigest(password+salt) | |
206 | + end | |
207 | + | |
201 | 208 | add_encryption_method :clear do |password, salt| |
202 | 209 | password |
203 | 210 | end |
... | ... | @@ -347,6 +354,7 @@ class User < ActiveRecord::Base |
347 | 354 | end |
348 | 355 | |
349 | 356 | def delay_activation_check |
357 | + return if person.is_template? | |
350 | 358 | Delayed::Job.enqueue(UserActivationJob.new(self.id), {:priority => 0, :run_at => 72.hours.from_now}) |
351 | 359 | end |
352 | 360 | end | ... | ... |
app/sweepers/role_assignment_sweeper.rb
... | ... | @@ -13,20 +13,22 @@ class RoleAssignmentSweeper < ActiveRecord::Observer |
13 | 13 | protected |
14 | 14 | |
15 | 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 | 18 | end |
19 | 19 | |
20 | 20 | def expire_cache(profile) |
21 | 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 | 26 | profile.blocks_to_expire_cache.each { |block| |
27 | 27 | blocks = profile.blocks.select{|b| b.kind_of?(block)} |
28 | 28 | BlockSweeper.expire_blocks(blocks) |
29 | 29 | } |
30 | + | |
31 | + expire_blocks_cache(profile, [:role_assignment]) | |
30 | 32 | end |
31 | 33 | |
32 | 34 | end | ... | ... |
app/views/admin_panel/index.html.erb
... | ... | @@ -20,6 +20,7 @@ |
20 | 20 | <tr><td><%= link_to _('Users'), :controller => 'users' %></td></tr> |
21 | 21 | <tr><td><%= link_to _('Profile templates'), :controller => 'templates' %></td></tr> |
22 | 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 | 24 | </table> |
24 | 25 | |
25 | 26 | ... | ... |
app/views/admin_panel/manage_organizations_status.html.erb
0 → 100644
... | ... | @@ -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 | 70 | \ No newline at end of file | ... | ... |
app/views/box_organizer/edit.html.erb
... | ... | @@ -5,6 +5,12 @@ |
5 | 5 | |
6 | 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 | 14 | <%= render :partial => partial_for_class(@block.class) %> |
9 | 15 | |
10 | 16 | <div class="display"> | ... | ... |
app/views/catalog/index.html.erb
... | ... | @@ -14,8 +14,8 @@ |
14 | 14 | |
15 | 15 | <ul id="product-list"> |
16 | 16 | <% @products.each do |product| %> |
17 | - <% extra_content = @plugins.dispatch(:catalog_item_extras, product).collect { |content| instance_eval(&content) } %> | |
18 | - <% extra_content_list = @plugins.dispatch(:catalog_list_item_extras, product).collect { |content| instance_eval(&content) } %> | |
17 | + <% extra_content = @plugins.dispatch(:catalog_item_extras, product).collect { |content| instance_exec(&content) } %> | |
18 | + <% extra_content_list = @plugins.dispatch(:catalog_list_item_extras, product).collect { |content| instance_exec(&content) } %> | |
19 | 19 | |
20 | 20 | <% status = [] %> |
21 | 21 | <% status << 'not-available' if !product.available %> | ... | ... |
app/views/cms/_general_fields.html.erb
1 | 1 | <%= select_profile_folder(_('Parent folder:'), 'article[parent_id]', profile, @article.parent_id) %> |
2 | -<%= labelled_form_field(_('License'), select(:article, :license_id, options_for_select_with_title([[_('None'), nil]] + profile.environment.licenses.map {|license| [license.name, license.id]}, @article.license ? @article.license.id : nil))) %> | |
2 | +<% if profile.environment.has_license? %> | |
3 | + <%= labelled_form_field(_('License'), select(:article, :license_id, options_for_select_with_title([[_('None'), nil]] + profile.environment.licenses.map {|license| [license.name, license.id]}, @article.license ? @article.license.id : nil))) %> | |
4 | +<% end %> | ... | ... |
app/views/cms/upload_files.html.erb
... | ... | @@ -20,5 +20,10 @@ |
20 | 20 | <h5><%= _('Uploading files to %s') % content_tag('code', @target) %></h5> |
21 | 21 | |
22 | 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 | 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 | 2 | <%= _('Content management') %> |
3 | 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 | 6 | <div class="cms-homepage"> |
7 | 7 | <%= _('Profile homepage:') %> |
8 | 8 | <% if profile.home_page %> |
... | ... | @@ -69,7 +69,7 @@ |
69 | 69 | <%= expirable_button article, :edit, _('Edit'), {:action => 'edit', :id => article.id} if !remove_content_button(:edit) %> |
70 | 70 | <%= button_without_text :eyes, _('Public view'), article.view_url %> |
71 | 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 | 73 | <% if profile.home_page != article %> |
74 | 74 | <%= expirable_button article, :home, _('Use as homepage'), { :action => 'set_home_page', :id => article.id }, :method => :post %> |
75 | 75 | <% else %> | ... | ... |
app/views/contact/new.html.erb
... | ... | @@ -13,11 +13,16 @@ |
13 | 13 | |
14 | 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 | 22 | <% unless environment.enabled?('disable_select_city_for_contact') || location_fields.blank? %> |
19 | 23 | <%= labelled_form_field _('City and state'), location_fields %> |
20 | 24 | <% end %> |
25 | + | |
21 | 26 | <%= required f.text_field(:subject) %> |
22 | 27 | |
23 | 28 | <%= render :file => 'shared/tiny_mce' %> |
... | ... | @@ -25,5 +30,9 @@ |
25 | 30 | |
26 | 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 | 38 | <% end %> | ... | ... |
app/views/content_viewer/view_page.html.erb
... | ... | @@ -70,37 +70,36 @@ |
70 | 70 | |
71 | 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 | 75 | <h3 <%= 'class="no-comments-yet"' if @comments_count == 0 %>> |
77 | 76 | <%= display_number_of_comments(@comments_count) %> |
78 | 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 | 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 | 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 | 104 | </div><!-- end id="article" --> |
106 | 105 | <%= add_zoom_to_article_images %> | ... | ... |
app/views/enterprise_registration/basic_information.html.erb
... | ... | @@ -20,7 +20,7 @@ |
20 | 20 | |
21 | 21 | <%= labelled_form_for :create_enterprise do |f| %> |
22 | 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 | 24 | <%= render :partial => 'shared/organization_custom_fields', :locals => { :f => f, :object_name => :create_enterprise, :profile => @create_enterprise } %> |
25 | 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 | 13 | date.day, |
14 | 14 | :url => {:action => 'events_by_day', :year => date.year, :month => date.month, :day => date.day, :category_id => @category_id}, |
15 | 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 | 19 | date.day |
20 | 20 | %> | ... | ... |
app/views/events/events.html.erb
... | ... | @@ -3,7 +3,7 @@ |
3 | 3 | <div id='agenda-toolbar'> |
4 | 4 | <%= button :back, _('Back to %s') % profile.name, profile.url %> |
5 | 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 | 7 | <% end %> |
8 | 8 | </div> |
9 | 9 | ... | ... |
app/views/file_presenter/_generic.html.erb
1 | 1 | <span class="download-link"> |
2 | 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 | 4 | </span> |
5 | 5 | |
6 | 6 | <div class="uploaded-file-description <%= 'empty' if generic.abstract.blank? %>"> | ... | ... |
app/views/file_presenter/_image.html.erb
... | ... | @@ -28,7 +28,7 @@ |
28 | 28 | |
29 | 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 | 33 | <div class="uploaded-file-description <%= 'empty' if image.abstract.blank? %>"> |
34 | 34 | <%= image.abstract %> | ... | ... |
app/views/home/index.html.erb
app/views/layouts/application-ng.html.erb
1 | 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 | 3 | <head> |
4 | 4 | <title><%= h page_title %></title> |
5 | 5 | <%= yield(:feeds) %> |
... | ... | @@ -12,20 +12,8 @@ |
12 | 12 | <meta name="twitter:title" content="<%= h page_title %>"> |
13 | 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 | 18 | <link rel="shortcut icon" href="<%= image_path(theme_favicon) %>" type="image/x-icon" /> |
31 | 19 | <%= noosfero_javascript %> |
... | ... | @@ -69,10 +57,7 @@ |
69 | 57 | <div id="navigation-end"></div> |
70 | 58 | </div><!-- end id="navigation" --> |
71 | 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 | 61 | </div><!-- end id="content" --> |
77 | 62 | </div><!-- end id="wrap-2" --> |
78 | 63 | </div><!-- end id="wrap-1" --> |
... | ... | @@ -81,7 +66,6 @@ |
81 | 66 | <%= theme_footer %> |
82 | 67 | </div><!-- end id="theme-footer" --> |
83 | 68 | <%= noosfero_layout_features %> |
84 | - <%= theme_javascript_ng %> | |
85 | 69 | <%= addthis_javascript %> |
86 | 70 | <%= |
87 | 71 | @plugins.dispatch(:body_ending).map do |content| | ... | ... |
app/views/layouts/application.html.erb
1 | 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 | 3 | <head> |
4 | 4 | <title><%= h page_title %></title> |
5 | 5 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> |
... | ... | @@ -68,7 +68,7 @@ |
68 | 68 | |
69 | 69 | <div id="navigation_bar"> |
70 | 70 | <%= link_to "<span>"+ @environment.name() +"</span>", |
71 | - @environment.top_url, | |
71 | + top_url, | |
72 | 72 | :id=>"menu_link_to_envhome", |
73 | 73 | :title=>@environment.name %> |
74 | 74 | <% unless environment.enabled?(:disable_categories) %> | ... | ... |
app/views/manage_products/_edit_description.html.erb
1 | 1 | <%= render :file => 'shared/tiny_mce', :locals => {:mode => 'simple'} %> |
2 | 2 | <%= remote_form_for(@product, |
3 | 3 | :loading => "small_loading('product-description-form')", |
4 | - :before => ("tinyMCE.triggerSave()" unless Rails.env == 'test'), | |
5 | 4 | :update => 'product-description', |
6 | 5 | :url => {:controller => 'manage_products', :action => 'edit', :id => @product, :field => 'description'}, |
7 | 6 | :html => {:id => 'product-description-form', :method => 'post'}) do |f| %> | ... | ... |
app/views/manage_products/_edit_info.html.erb
... | ... | @@ -47,7 +47,7 @@ |
47 | 47 | <%= button_to_function( |
48 | 48 | :add, |
49 | 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 | 52 | <%= hidden_field_tag "product[qualifiers_list][nil]" %> |
53 | 53 | <% end %> | ... | ... |
app/views/manage_products/show.html.erb
... | ... | @@ -13,7 +13,7 @@ |
13 | 13 | <%= render :partial => 'manage_products/display_image' %> |
14 | 14 | </div> |
15 | 15 | <div id='product-extra-content'> |
16 | - <% extra_content = @plugins.dispatch(:product_info_extras, @product).collect { |content| instance_eval(&content) } %> | |
16 | + <% extra_content = @plugins.dispatch(:product_info_extras, @product).collect { |content| instance_exec(&content) } %> | |
17 | 17 | <%= extra_content.join("\n") %> |
18 | 18 | </div> |
19 | 19 | <div id='product-info'> | ... | ... |
app/views/profile/_common.html.erb
1 | 1 | <% unless @action %> |
2 | 2 | <% cache_timeout(profile.cache_key + '-profile-general-info', 4.hours) do %> |
3 | - <tr> | |
4 | - <th colspan='2'> | |
5 | - <%= _('Content') %> | |
6 | - </th> | |
7 | - </tr> | |
8 | - | |
9 | - <% profile.blogs.each do |blog| %> | |
10 | - <tr> | |
11 | - <td><%= blog.name + ':' %></td> | |
12 | - <td> | |
13 | - <%= link_to(n_('One post', '%{num} posts', blog.posts.published.count) % { :num => blog.posts.published.count }, blog.url) %> | |
14 | - </td> | |
15 | - </tr> | |
16 | - <% end %> | |
17 | - <% profile.image_galleries.each do |gallery| %> | |
18 | - <tr> | |
19 | - <td><%= gallery.name + ':' %></td> | |
20 | - <td> | |
21 | - <%= link_to(n_('One picture', '%{num} pictures', gallery.images.published.count) % { :num => gallery.images.published.count }, gallery.url) %> | |
22 | - </td> | |
23 | - </tr> | |
24 | - <% end %> | |
25 | - | |
26 | - <tr> | |
27 | - <td><%= _('Events:') %></td> | |
28 | - <td> | |
29 | - <%= link_to profile.events.published.count, :controller => 'events', :action => 'events' %> | |
30 | - </td> | |
31 | - </tr> | |
32 | - <tr> | |
33 | - <td> | |
34 | - <%= _('Tags:') %> | |
35 | - </td> | |
36 | - <td> | |
37 | - <%= tag_cloud @tags, :id, { :action => 'tags' }, :max_size => 18, :min_size => 10%> | |
38 | - </td> | |
39 | - </tr> | |
3 | + <%= display_content %> | |
40 | 4 | |
41 | 5 | <% if !environment.enabled?('disable_categories') && !profile.interests.empty? %> |
42 | - <tr> | |
43 | - <th colspan='2'><%= _('Interests') %></th> | |
44 | - </tr> | |
45 | - <% profile.interests.each do |item| %> | |
46 | - <tr> | |
47 | - <td></td> | |
48 | - <td><%= link_to item.name, :controller => 'search', :action => 'category_index', :category_path => item.explode_path %></td> | |
49 | - </tr> | |
50 | - <% end %> | |
6 | + <%= display_interests %> | |
51 | 7 | <% end %> |
8 | + | |
9 | + <%= display_general %> | |
52 | 10 | <% end %> |
53 | 11 | <% end %> | ... | ... |
app/views/profile/_organization_profile.html.erb
1 | 1 | <table> |
2 | - <tr> | |
3 | - <th colspan='2'><%= _('Basic information')%></th> | |
4 | - </tr> | |
5 | - | |
6 | - <tr> | |
7 | - <td class='field-name'><%= _('Members') %></td> | |
8 | - <td> | |
9 | - <%= link_to profile.members_count, :controller => 'profile', :action => 'members' %> | |
10 | - </td> | |
11 | - </tr> | |
12 | - | |
13 | - <%= display_field(_('Type:'), profile, :privacy_setting, true) %> | |
14 | - | |
15 | - <%= display_field(_('Location:'), profile, :location, true) %> | |
16 | - | |
17 | - <tr> | |
18 | - <td class='field-name'><%= _('Profile created at:') %></td> | |
19 | - <td><%= show_date(profile.created_at) %></td> | |
20 | - </tr> | |
21 | - | |
22 | - <% if profile.kind_of?(Enterprise) && profile.environment.enabled?('products_for_enterprises') %> | |
23 | - <tr> | |
24 | - <td></td> | |
25 | - <td> | |
26 | - <%= link_to _('Products/Services'), :controller => 'catalog', :action => 'index' %> | |
27 | - </td> | |
28 | - </tr> | |
29 | - <% end %> | |
30 | - | |
31 | - <tr> | |
32 | - <td class='field-name'><%= _('Administrators:') %></td> | |
33 | - <td> | |
34 | - <%= profile.admins.map { |admin| link_to(admin.short_name, admin.url)}.join(', ') %> | |
35 | - </td> | |
36 | - </tr> | |
37 | - | |
2 | + <%= display_basic_information %> | |
3 | + <%= display_contact %> | |
4 | + <%= display_economic %> | |
38 | 5 | <%= render :partial => 'common' %> |
39 | 6 | </table> | ... | ... |
app/views/profile/_person_profile.html.erb
1 | 1 | <table> |
2 | - <tr> | |
3 | - <th colspan='2'><%= _('Basic information')%></th> | |
4 | - </tr> | |
5 | - <%= display_field(_('Sex:'), profile, :sex) { |gender| { 'male' => _('Male'), 'female' => _('Female') }[gender] } %> | |
6 | - <%= display_field(_('Date of birth:'), profile, :birth_date) { |date| show_date(date) }%> | |
7 | - <%= display_field _('Location:'), profile, :location %> | |
8 | - | |
9 | - <%= display_field(_('Type:'), profile, :privacy_setting, true) %> | |
10 | - | |
11 | - <tr> | |
12 | - <td class='field-name'><%= _('Profile created at:') %></td> | |
13 | - <td><%= show_date(profile.created_at) %></td> | |
14 | - </tr> | |
15 | - | |
16 | - <%= display_contact profile %> | |
2 | + <%= display_basic_information %> | |
3 | + <%= display_contact %> | |
4 | + <%= display_location %> | |
17 | 5 | |
18 | 6 | <% cache_timeout(profile.relationships_cache_key, 4.hours) do %> |
19 | - <%= display_work_info profile %> | |
20 | - | |
21 | - <%= display_custom_fields(profile) %> | |
22 | - | |
23 | - <tr> | |
24 | - <th colspan='2'><%= _('Network')%></th> | |
25 | - </tr> | |
26 | - <tr> | |
27 | - <td><%= _('Friends') + ':' %></td> | |
28 | - <td><%= link_to profile.friends.count, { :controller => 'profile', :action => 'friends' } %></td> | |
29 | - </tr> | |
30 | - <tr> | |
31 | - <td><%= _('Communities') + ':' %></td> | |
32 | - <td><%= link_to profile.communities.count, :controller => "profile", :action => 'communities' %></td> | |
33 | - </tr> | |
34 | - <% if environment.disabled?('disable_asset_enterprises') %> | |
35 | - <tr id="person-profile-network-enterprises"> | |
36 | - <td><%= _('Enterprises') + ':' %></td> | |
37 | - <td><%= link_to profile.enterprises.count, :controller => "profile", :action => 'enterprises' %></td> | |
38 | - </tr> | |
39 | - <% end %> | |
7 | + <%= display_work %> | |
8 | + <%= display_study %> | |
9 | + <%= display_network %> | |
10 | + <%= display_custom_fields(profile) %> | |
40 | 11 | |
41 | 12 | <%= render :partial => 'common' %> |
42 | - | |
43 | 13 | <% end %> |
44 | 14 | </table> |
15 | + | ... | ... |
app/views/profile/_profile_comment_form.html.erb
... | ... | @@ -10,8 +10,8 @@ |
10 | 10 | :rows => 1, |
11 | 11 | :class => 'submit-with-keypress', |
12 | 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 | 15 | :value => _('Leave your comment'), |
16 | 16 | :style => 'color: #ccc' %> |
17 | 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 | 9 | :rows => 1, |
10 | 10 | :class => 'submit-with-keypress', |
11 | 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 | 14 | :value => _('Leave your comment') %> |
15 | 15 | <%= hidden_field_tag 'scrap[scrap_id]', scrap.id %> |
16 | 16 | <%= hidden_field_tag 'receiver_id', scrap.sender.id %> | ... | ... |
app/views/profile_editor/_person_form.html.erb
... | ... | @@ -25,6 +25,11 @@ |
25 | 25 | <%= optional_field(@person, 'address', labelled_form_field(_('Address (street and number)'), text_field(:profile_data, :address, :rel => _('Address')))) %> |
26 | 26 | <%= optional_field(@person, 'address_reference', labelled_form_field(_('Address reference'), text_field(:profile_data, :address_reference, :rel => _('Address reference')))) %> |
27 | 27 | <%= optional_field(@person, 'district', labelled_form_field(_('District'), text_field(:profile_data, :district, :rel => _('District')))) %> |
28 | +<%= optional_field(@person, 'image', labelled_form_field(_('Image'), file_field(:file, :image, :rel => _('Image')))) %> | |
29 | + | |
30 | +<% @plugins.dispatch(:extra_optional_fields).each do |field| %> | |
31 | + <%= optional_field(@person, field[:name], labelled_form_field(field[:label], text_field(field[:object_name], field[:method], :rel => field[:label], :value => field[:value]))) %> | |
32 | +<% end %> | |
28 | 33 | |
29 | 34 | <% optional_field(@person, 'schooling') do %> |
30 | 35 | <div class="formfieldline"> | ... | ... |
app/views/profile_editor/edit.html.erb
1 | 1 | <h1><%= _('Profile settings for %s') % profile.name %></h1> |
2 | 2 | |
3 | +<%= javascript_include_tag 'deactivate_profile' %> | |
3 | 4 | <%= error_messages_for :profile_data %> |
4 | 5 | |
5 | 6 | <%= labelled_form_for :profile_data, :html => { :id => 'profile-data', :multipart => true } do |f| %> |
... | ... | @@ -67,6 +68,15 @@ |
67 | 68 | <% if user && user.has_permission?('destroy_profile', profile) %> |
68 | 69 | <% button_bar(:id => 'delete-profile') do %> |
69 | 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 | 80 | <% end %> |
71 | 81 | <% end %> |
72 | 82 | -<% end %> |
83 | +<% end %> | |
73 | 84 | \ No newline at end of file | ... | ... |
app/views/role/_form.html.erb
... | ... | @@ -6,10 +6,14 @@ |
6 | 6 | |
7 | 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 | 17 | <% end %> |
14 | 18 | |
15 | 19 | <% button_bar do %> | ... | ... |
app/views/role/edit.html.erb
1 | 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 | 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 | 14 | |
15 | 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 | 18 | <ul> |
19 | 19 | <% search[:results].each do |hit| %> |
20 | 20 | <% partial = partial_for_class(hit.class, display) %> | ... | ... |
app/views/shared/reported_versions/_article.html.erb
... | ... | @@ -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 | -<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 | -<%= _('Reported folder') + ': ' + link_to(article.name, article.url) %> |
app/views/shared/reported_versions/profile/_article.html.erb
0 → 100644
... | ... | @@ -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 @@ |
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 @@ |
1 | +<%= _('Reported folder') + ': ' + link_to(article.name, article.url) %> | ... | ... |