Commit 87ccdfde777a2f6d1ef511c6a052ae68e298fee9

Authored by Victor Costa
2 parents 40c630fd 24b3013c
Exists in staging

Merge branch 'master' into staging

Showing 2490 changed files with 297841 additions and 297897 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 2490 files displayed.

.gitlab-ci.yml
@@ -59,18 +59,18 @@ selenium-6: @@ -59,18 +59,18 @@ selenium-6:
59 # NOOSFERO_BUNDLE_OPTS=install makes migrations fails 59 # NOOSFERO_BUNDLE_OPTS=install makes migrations fails
60 # probably because of rubygems-integration 60 # probably because of rubygems-integration
61 plugins-1: 61 plugins-1:
62 - script: SLICE=1/5 bundle exec rake test:noosfero_plugins 62 + script: SLICE=1/5 bundle exec rake test:noosfero_plugins NOOSFERO_BUNDLE_OPTS=install
63 stage: all-tests 63 stage: all-tests
64 plugins-2: 64 plugins-2:
65 - script: SLICE=2/5 bundle exec rake test:noosfero_plugins 65 + script: SLICE=2/5 bundle exec rake test:noosfero_plugins NOOSFERO_BUNDLE_OPTS=install
66 stage: all-tests 66 stage: all-tests
67 plugins-3: 67 plugins-3:
68 - script: SLICE=3/5 bundle exec rake test:noosfero_plugins 68 + script: SLICE=3/5 bundle exec rake test:noosfero_plugins NOOSFERO_BUNDLE_OPTS=install
69 stage: all-tests 69 stage: all-tests
70 plugins-4: 70 plugins-4:
71 - script: SLICE=4/5 bundle exec rake test:noosfero_plugins 71 + script: SLICE=4/5 bundle exec rake test:noosfero_plugins NOOSFERO_BUNDLE_OPTS=install
72 stage: all-tests 72 stage: all-tests
73 plugins-5: 73 plugins-5:
74 - script: SLICE=5/5 bundle exec rake test:noosfero_plugins 74 + script: SLICE=5/5 bundle exec rake test:noosfero_plugins NOOSFERO_BUNDLE_OPTS=install
75 stage: all-tests 75 stage: all-tests
76 76
@@ -19,6 +19,10 @@ language: ruby @@ -19,6 +19,10 @@ language: ruby
19 rvm: 19 rvm:
20 - 2.3.1 20 - 2.3.1
21 21
  22 +services:
  23 + - postgresql
  24 + - elasticsearch
  25 +
22 addons: 26 addons:
23 apt: 27 apt:
24 packages: 28 packages:
@@ -8,38 +8,42 @@ noosfero, that's not a problem). @@ -8,38 +8,42 @@ noosfero, that's not a problem).
8 Developers 8 Developers
9 ========== 9 ==========
10 10
11 -Ábner Silva de Oliveira <abner.oliveira@serpro.gov.br>  
12 Alan Freihof Tygel <alantygel@gmail.com> 11 Alan Freihof Tygel <alantygel@gmail.com>
  12 +Alessandro Caetano <alesasndro.caetanob@gmail.com>
  13 +Alessandro Caetano <alessandro.caetanob@gmail.com>
13 Alessandro Palmeira <alessandro.palmeira@gmail.com> 14 Alessandro Palmeira <alessandro.palmeira@gmail.com>
  15 +Alex Campelo <campelo.al1@gmail.com>
14 Alexandre Barbosa <alexandreab@live.com> 16 Alexandre Barbosa <alexandreab@live.com>
15 Alexandre Torres <alexandrekry@gmail.com> 17 Alexandre Torres <alexandrekry@gmail.com>
16 -Alex Campelo <campelo.al1@gmail.com>  
17 -Álvaro Fernando <alvarofernandoms@gmail.com> 18 +Alipio muñiz <alipio@ecoalternative.net>
18 Ana Losnak <analosnak@gmail.com> 19 Ana Losnak <analosnak@gmail.com>
19 Ana Paula Vargas <anapaulavnoronha@gmail.com> 20 Ana Paula Vargas <anapaulavnoronha@gmail.com>
20 Andre Bedran <bedran.fleck@gmail.com> 21 Andre Bedran <bedran.fleck@gmail.com>
21 -André Guedes <andrebsguedes@gmail.com>  
22 Andrey Aleksanyants <aaleksanyants@yahoo.com> 22 Andrey Aleksanyants <aaleksanyants@yahoo.com>
  23 +André Guedes <andrebsguedes@gmail.com>
23 Antonio Terceiro <terceiro@colivre.coop.br> 24 Antonio Terceiro <terceiro@colivre.coop.br>
24 Arthur Del Esposte <arthurmde@gmail.com> 25 Arthur Del Esposte <arthurmde@gmail.com>
  26 +Arthur Jahn <stutrzbecher@gmail.com>
  27 +Artur Bersan de Faria <arturbersan@gmail.com>
25 Athos Ribeiro <athoscribeiro@gmail.com> 28 Athos Ribeiro <athoscribeiro@gmail.com>
26 -Aurelio A. Heckert <aurelio@colivre.coop.br> 29 +Aurelio A. Heckert <aurium@colivre.coop.br>
  30 +Becca Cook <b.cook28@gmail.com>
27 Braulio Bhavamitra <braulio@eita.org.br> 31 Braulio Bhavamitra <braulio@eita.org.br>
28 Brenddon Gontijo <brenddongontijo@msn.com> 32 Brenddon Gontijo <brenddongontijo@msn.com>
29 Caio Formiga <caio.formiga@gmail.com> 33 Caio Formiga <caio.formiga@gmail.com>
30 -Caio Salgado <caio.csalgado@gmail.com>  
31 Caio SBA <caio@colivre.coop.br> 34 Caio SBA <caio@colivre.coop.br>
  35 +Caio Salgado <caio.csalgado@gmail.com>
32 Caio Tiago Oliveira <caiotiago@colivre.coop.br> 36 Caio Tiago Oliveira <caiotiago@colivre.coop.br>
33 Carlos Andre de Souza <carlos.andre.souza@msn.com> 37 Carlos Andre de Souza <carlos.andre.souza@msn.com>
34 Carlos Morais <carlos88morais@gmail.com> 38 Carlos Morais <carlos88morais@gmail.com>
35 Carlos Purificacao <carloseugenio@gmail.com> 39 Carlos Purificacao <carloseugenio@gmail.com>
36 Christophe DANIEL <papaeng@gmail.com> 40 Christophe DANIEL <papaeng@gmail.com>
37 -Daniela Feitosa <alessandro.palmeira@gmail.com>  
38 Daniel Alves <danpaulalves@gmail.com> 41 Daniel Alves <danpaulalves@gmail.com>
39 -Daniela Soares Feitosa <danielafeitosa@colivre.coop.br>  
40 Daniel Bucher <daniel.bucher88@gmail.com> 42 Daniel Bucher <daniel.bucher88@gmail.com>
41 Daniel Cunha <daniel@colivre.coop.br> 43 Daniel Cunha <daniel@colivre.coop.br>
  44 +Daniel Henrique <danielhmarinho@gmail.com>
42 Daniel Tygel <dtygel@eita.org.br> 45 Daniel Tygel <dtygel@eita.org.br>
  46 +Daniela Soares Feitosa <danielafeitosa@colivre.coop.br>
43 David Carlos <ddavidcarlos1392@gmail.com> 47 David Carlos <ddavidcarlos1392@gmail.com>
44 Diego Araujo <diegoamc90@gmail.com> 48 Diego Araujo <diegoamc90@gmail.com>
45 Dylan Guedes <djmgguedes@gmail.com> 49 Dylan Guedes <djmgguedes@gmail.com>
@@ -48,76 +52,91 @@ Eduardo Passos &lt;eduardosteps@gmail.com&gt; @@ -48,76 +52,91 @@ Eduardo Passos &lt;eduardosteps@gmail.com&gt;
48 Eduardo Tourinho Edington <eduardo.edington@serpro.gov.br> 52 Eduardo Tourinho Edington <eduardo.edington@serpro.gov.br>
49 Eduardo Vital <vitaldu@gmail.com> 53 Eduardo Vital <vitaldu@gmail.com>
50 Evandro Magalhaes Leite Junior <evandro.leite@serpro.gov.br> 54 Evandro Magalhaes Leite Junior <evandro.leite@serpro.gov.br>
51 -Fabio Teixeira <fabio1079@gmail.com>  
52 FAMMA TV NOTICIAS MEDIOS DE CO <revistafammatvmusic.oficial@gmail.com> 55 FAMMA TV NOTICIAS MEDIOS DE CO <revistafammatvmusic.oficial@gmail.com>
  56 +Fabio Teixeira <fabio1079@gmail.com>
  57 +Fagner Rodrigues <fagner128@gmail.com>
53 Fernanda Lopes <nanda.listas+psl@gmail.com> 58 Fernanda Lopes <nanda.listas+psl@gmail.com>
54 Filipe Ribeiro <firibeiro77@live.com> 59 Filipe Ribeiro <firibeiro77@live.com>
55 Francisco Marcelo de Araújo Lima Júnior <francisco.lima-junior@serpro.gov.br> 60 Francisco Marcelo de Araújo Lima Júnior <francisco.lima-junior@serpro.gov.br>
56 -Gabriela Navarro <navarro1703@gmail.com>  
57 Gabriel Silva <gabriel93.silva@gmail.com> 61 Gabriel Silva <gabriel93.silva@gmail.com>
  62 +Gabriel Silva <grabriel93.silva@gmail.com>
  63 +Gabriela Navarro <navarro1703@gmail.com>
58 Gonzalo Exequiel Pedone <hipersayan.x@gmail.com> 64 Gonzalo Exequiel Pedone <hipersayan.x@gmail.com>
59 Grazieno Pellegrino <grazieno@gmail.com> 65 Grazieno Pellegrino <grazieno@gmail.com>
60 Guilherme C. Muniz <guilherme.cmuniz@gmail.com> 66 Guilherme C. Muniz <guilherme.cmuniz@gmail.com>
61 Guilherme Rojas <guilhermehrojas@gmail.com> 67 Guilherme Rojas <guilhermehrojas@gmail.com>
  68 +Gustavo Cavalcante <gustavo.cavalcante.oliveira@live.com>
62 Gustavo Coelho <gust.rod.coelho@gmail.com> 69 Gustavo Coelho <gust.rod.coelho@gmail.com>
  70 +Gustavo Jaruga <darkshades@gmail.com>
63 Gustavo Jaruga <darksshades@gmail.com> 71 Gustavo Jaruga <darksshades@gmail.com>
64 Hebert Douglas <hebertdougl@gmail.com> 72 Hebert Douglas <hebertdougl@gmail.com>
65 Hugo Melo <hugo@riseup.net> 73 Hugo Melo <hugo@riseup.net>
  74 +Iago Rodrigues <iago006@hotmailcom>
66 Iolane Andrade <andrade.icaa@gmail.com> 75 Iolane Andrade <andrade.icaa@gmail.com>
  76 +Iryna Pruitt <jdpruitt2807@prodigy.net>
67 Isaac Canan <isaac@intelletto.com.br> 77 Isaac Canan <isaac@intelletto.com.br>
68 Italo Valcy <italo@dcc.ufba.br> 78 Italo Valcy <italo@dcc.ufba.br>
  79 +Izharul Haq <atoz.chevara.2013@gmail.com>
69 Jefferson Fernandes <jeffs.fernandes@gmail.com> 80 Jefferson Fernandes <jeffs.fernandes@gmail.com>
70 -Jérôme Jutteau <j.jutteau@gmail.com>  
71 -Jéssica Cristina <jessica.cris1127@gmail.com>  
72 -João Machini  
73 -João M. M. da Silva <jaodsilv@linux.ime.usp.br>  
74 Joenio Costa <joenio@colivre.coop.br> 81 Joenio Costa <joenio@colivre.coop.br>
75 -Josef Spillner <josef.spillner@tu-dresden.de> 82 +Joenio Costa <joenio@joenio.me>
76 Jose Pedro <1jpsneto@gmail.com> 83 Jose Pedro <1jpsneto@gmail.com>
  84 +Josef Spillner <josef.spillner@tu-dresden.de>
  85 +João M. M. da Silva <jaodsilv@linux.ime.usp.br>
  86 +João Machini
77 Junior Silva <juniorsilva1001@gmail.com> 87 Junior Silva <juniorsilva1001@gmail.com>
  88 +Jérôme Jutteau <j.jutteau@gmail.com>
  89 +Jéssica Cristina <jessica.cris1127@gmail.com>
  90 +Karine Valença <valenca.karine@gmail.com>
78 Keilla Menezes <keilla@colivre.coop.br> 91 Keilla Menezes <keilla@colivre.coop.br>
79 Larissa Reis <larissa@colivre.coop.br> 92 Larissa Reis <larissa@colivre.coop.br>
80 Leandro Alves <leandrosustenido@gmail.com> 93 Leandro Alves <leandrosustenido@gmail.com>
81 Leandro Nunes dos Santos <leandro.santos@serpro.gov.br> 94 Leandro Nunes dos Santos <leandro.santos@serpro.gov.br>
82 Leandro Veloso <leandrovelosorodrigues@gmail.com> 95 Leandro Veloso <leandrovelosorodrigues@gmail.com>
83 LinguÁgil 2010 <linguagil.bahia@gmail.com> 96 LinguÁgil 2010 <linguagil.bahia@gmail.com>
  97 +Luan Guimarães <guimaraesluan@me.com>
84 Lucas Couto <loc.unb@gmail.com> 98 Lucas Couto <loc.unb@gmail.com>
85 Lucas Kanashiro <kanashiro.duarte@gmail.com> 99 Lucas Kanashiro <kanashiro.duarte@gmail.com>
86 Lucas Melo <lucaspradomelo@gmail.com> 100 Lucas Melo <lucaspradomelo@gmail.com>
  101 +Lucas Moura <lucas.moura128@gmail.com>
  102 +Lucas Severo <lucassalves65@gmail.com>
87 Luciano Prestes Cavalcanti <lucianopcbr@gmail.com> 103 Luciano Prestes Cavalcanti <lucianopcbr@gmail.com>
88 Luis David Aguilar Carlos <ludwig9003@gmail.com> 104 Luis David Aguilar Carlos <ludwig9003@gmail.com>
89 Luiz Fernando de Freitas Matos <luiz@luizff.matos@gmail.com> 105 Luiz Fernando de Freitas Matos <luiz@luizff.matos@gmail.com>
90 Luiz Matos <luizff.matos@gmail.com> 106 Luiz Matos <luizff.matos@gmail.com>
  107 +M for Momo <mo@rtnp.org>
91 Macartur de Sousa <macartur.sc@gmail.com> 108 Macartur de Sousa <macartur.sc@gmail.com>
92 Marcelo Júnior <maljunior@gmail.com> 109 Marcelo Júnior <maljunior@gmail.com>
93 Marcos Ramos <ms.ramos@outlook.com> 110 Marcos Ramos <ms.ramos@outlook.com>
94 Marcos Ronaldo <marcos.rpj2@gmail.com> 111 Marcos Ronaldo <marcos.rpj2@gmail.com>
95 -María Vecino <mariavecino@ecoalternative.net>  
96 Mariel Zasso <noosfero-br@listas.softwarelivre.org> 112 Mariel Zasso <noosfero-br@listas.softwarelivre.org>
97 Martín Olivera <molivera@solar.org.ar> 113 Martín Olivera <molivera@solar.org.ar>
  114 +María Vecino <mariavecino@ecoalternative.net>
98 Matheus Faria <matheus.sousa.faria@gmail.com> 115 Matheus Faria <matheus.sousa.faria@gmail.com>
  116 +Matheus Miranda <matheusmirandalacerda@gmail.com>
99 Maurilio Atila <cabelotaina@gmail.com> 117 Maurilio Atila <cabelotaina@gmail.com>
100 Melissa Wen <melissa.srw@gmail.com> 118 Melissa Wen <melissa.srw@gmail.com>
101 -M for Momo <mo@rtnp.org>  
102 Michal Čihař <michal@cihar.com> 119 Michal Čihař <michal@cihar.com>
103 Michel Felipe de Oliveira Ferreira <michel.ferreira@serpro.gov.br> 120 Michel Felipe de Oliveira Ferreira <michel.ferreira@serpro.gov.br>
104 Moises Machado <moises@colivre.coop.br> 121 Moises Machado <moises@colivre.coop.br>
105 -Naíla Alves <naila@colivre.coop.br> 122 +Murilo Duarte <muriloduartegoncalves@hotmail.com>
106 Nanda Lopes <nanda.listas+psl@gmail.com> 123 Nanda Lopes <nanda.listas+psl@gmail.com>
  124 +Naíla Alves <naila@colivre.coop.br>
107 Niemand Jedermann <predatorix@web.de> 125 Niemand Jedermann <predatorix@web.de>
108 Omar Junior <omarroinuj@gmail.com> 126 Omar Junior <omarroinuj@gmail.com>
109 Parley Martins <parleypachecomartins@gmail.com> 127 Parley Martins <parleypachecomartins@gmail.com>
110 Paulo Meirelles <paulo@softwarelivre.org> 128 Paulo Meirelles <paulo@softwarelivre.org>
111 -Pedro de Lyra <pedrodelyra@gmail.com> 129 +Paulo Tada <paulohtfs@gmail.com>
112 Pedro Leal 130 Pedro Leal
  131 +Pedro de Lyra <pedrodelyra@gmail.com>
113 Phillip Rohmberger <rohmberger@hotmail.de> 132 Phillip Rohmberger <rohmberger@hotmail.de>
114 -Rafael de Souza Queiroz <querafael@live.com>  
115 Rafael Gomes <rafaelgomes@techfree.com.br> 133 Rafael Gomes <rafaelgomes@techfree.com.br>
116 Rafael Martins <rmmartins@gmail.com> 134 Rafael Martins <rmmartins@gmail.com>
117 Rafael Reggiani Manzo <rr.manzo@gmail.com> 135 Rafael Reggiani Manzo <rr.manzo@gmail.com>
  136 +Rafael de Souza Queiroz <querafael@live.com>
118 Raphaël Rousseau <raph@r4f.org> 137 Raphaël Rousseau <raph@r4f.org>
119 -Raquel Lira <raquel.lira@gmail.com>  
120 Raquel <rcordioli@gmail.com> 138 Raquel <rcordioli@gmail.com>
  139 +Raquel Lira <raquel.lira@gmail.com>
121 Renan Costa <renan2727@hotmail.com> 140 Renan Costa <renan2727@hotmail.com>
122 Renan Teruo <renanteruoc@gmail.com> 141 Renan Teruo <renanteruoc@gmail.com>
123 Rodrigo Medeiros <rodrigo.mss01@gmail.com> 142 Rodrigo Medeiros <rodrigo.mss01@gmail.com>
@@ -125,16 +144,18 @@ Rodrigo Siqueira &lt;siqueira@kuniri.org&gt; @@ -125,16 +144,18 @@ Rodrigo Siqueira &lt;siqueira@kuniri.org&gt;
125 Rodrigo Souto <rodrigo@colivre.coop.br> 144 Rodrigo Souto <rodrigo@colivre.coop.br>
126 Ronnie Simon <ronniesimonf@gmail.com> 145 Ronnie Simon <ronniesimonf@gmail.com>
127 Ronny Kursawe <kursawe.ronny@googlemail.com> 146 Ronny Kursawe <kursawe.ronny@googlemail.com>
  147 +Sabryna Sousa <sabryna.sousa1323@gmail.com>
128 Samuel R. C. Vale <srcvale@holoscopio.com> 148 Samuel R. C. Vale <srcvale@holoscopio.com>
129 Simião Carvalho <simiaosimis@gmail.com> 149 Simião Carvalho <simiaosimis@gmail.com>
  150 +TWS <tablettws@gmail.com>
130 Tallys Martins <tallysmartins@yahoo.com.br> 151 Tallys Martins <tallysmartins@yahoo.com.br>
131 Thiago Casotti <thiago.casotti@uol.com.br> 152 Thiago Casotti <thiago.casotti@uol.com.br>
132 Thiago Kairala <thiagor.kairala@gmail.com> 153 Thiago Kairala <thiagor.kairala@gmail.com>
133 Thiago Ribeiro <thiagitosouza@hotmail.com> 154 Thiago Ribeiro <thiagitosouza@hotmail.com>
134 Thiago Zoroastro <thiago.zoroastro@bol.com.br> 155 Thiago Zoroastro <thiago.zoroastro@bol.com.br>
135 Tuux <tuxa@galaxie.eu.org> 156 Tuux <tuxa@galaxie.eu.org>
136 -TWS <tablettws@gmail.com>  
137 Valessio Brito <contato@valessiobrito.com.br> 157 Valessio Brito <contato@valessiobrito.com.br>
  158 +Valet 322 <petymakar@gmail.com>
138 Victor Costa <vfcosta@gmail.com> 159 Victor Costa <vfcosta@gmail.com>
139 Victor Hugo Alves de Carvalho <victorhugodf.ac@gmail.com> 160 Victor Hugo Alves de Carvalho <victorhugodf.ac@gmail.com>
140 Victor Navarro <victor.matias.navarro@gmail.com> 161 Victor Navarro <victor.matias.navarro@gmail.com>
@@ -142,6 +163,9 @@ Vinicius Brand &lt;viniciuscb@gmail.com&gt; @@ -142,6 +163,9 @@ Vinicius Brand &lt;viniciuscb@gmail.com&gt;
142 Vitor Barbosa <vitornga15@gmail.com> 163 Vitor Barbosa <vitornga15@gmail.com>
143 Wilton Rodrigues <braynwilton@gmail.com> 164 Wilton Rodrigues <braynwilton@gmail.com>
144 Yann Lugrin <yann.lugrin@liquid-concept.ch> 165 Yann Lugrin <yann.lugrin@liquid-concept.ch>
  166 +Ábner Silva de Oliveira <abner.oliveira@serpro.gov.br>
  167 +Álvaro Fernando <alvarofernandoms@gmail.com>
  168 +Вадим Кардашьян <iosphone77@gmail.com>
145 169
146 Ideas, specifications and incentive 170 Ideas, specifications and incentive
147 =================================== 171 ===================================
@@ -27,7 +27,7 @@ gem &#39;rest-client&#39;, &#39;~&gt; 1.6&#39; @@ -27,7 +27,7 @@ gem &#39;rest-client&#39;, &#39;~&gt; 1.6&#39;
27 gem 'exception_notification', '~> 4.0.1' 27 gem 'exception_notification', '~> 4.0.1'
28 gem 'gettext', '~> 3.1', :require => false 28 gem 'gettext', '~> 3.1', :require => false
29 gem 'locale', '~> 2.1' 29 gem 'locale', '~> 2.1'
30 -gem 'whenever', :require => false 30 +gem 'whenever', '~> 0.9.4', :require => false
31 gem 'eita-jrails', '~> 0.10.0', require: 'jrails' 31 gem 'eita-jrails', '~> 0.10.0', require: 'jrails'
32 gem 'diffy', '~> 3.0' 32 gem 'diffy', '~> 3.0'
33 gem 'slim' 33 gem 'slim'
@@ -35,17 +35,16 @@ gem &#39;activerecord-session_store&#39;, (&#39;1.0.0.pre&#39; if RUBY_VERSION &gt;= &#39;2.3.0&#39;) @@ -35,17 +35,16 @@ gem &#39;activerecord-session_store&#39;, (&#39;1.0.0.pre&#39; if RUBY_VERSION &gt;= &#39;2.3.0&#39;)
35 35
36 # API dependencies 36 # API dependencies
37 gem 'grape', '~> 0.12' 37 gem 'grape', '~> 0.12'
38 -gem 'grape-entity', '0.4.8' 38 +gem 'grape-entity', '~>0.4.8'
39 gem 'grape_logging' 39 gem 'grape_logging'
40 gem 'grape-swagger' 40 gem 'grape-swagger'
41 gem 'swagger-ui_rails' 41 gem 'swagger-ui_rails'
42 gem 'kramdown' 42 gem 'kramdown'
43 gem 'rack-cors' 43 gem 'rack-cors'
44 gem 'rack-contrib' 44 gem 'rack-contrib'
45 -gem 'liquid', '~> 3.0.3'  
46 45
47 gem 'api-pagination', '>= 4.1.1' 46 gem 'api-pagination', '>= 4.1.1'
48 -gem 'liquid', '~> 3.0.3' 47 +gem 'liquid', '>= 3.0.3'
49 48
50 # asset pipeline 49 # asset pipeline
51 gem 'uglifier', '>= 1.0.3' 50 gem 'uglifier', '>= 1.0.3'
@@ -81,10 +80,10 @@ end @@ -81,10 +80,10 @@ end
81 group :cucumber do 80 group :cucumber do
82 gem 'capybara', '~> 2.2' 81 gem 'capybara', '~> 2.2'
83 gem 'launchy' 82 gem 'launchy'
84 - gem 'cucumber' 83 + gem 'cucumber', '~> 1.3'
85 gem 'cucumber-rails', '~> 1.4.2', :require => false 84 gem 'cucumber-rails', '~> 1.4.2', :require => false
86 gem 'database_cleaner', '~> 1.3' 85 gem 'database_cleaner', '~> 1.3'
87 - gem 'selenium-webdriver', '>= 2.50' 86 + gem 'selenium-webdriver', '>= 2.53'
88 gem 'chromedriver-helper' if ENV['SELENIUM_DRIVER'] == 'chrome' 87 gem 'chromedriver-helper' if ENV['SELENIUM_DRIVER'] == 'chrome'
89 end 88 end
90 89
@@ -31,7 +31,7 @@ If you want to use a different port than 3000, pass `-p &lt;PORT&gt;` to `./script/dev @@ -31,7 +31,7 @@ If you want to use a different port than 3000, pass `-p &lt;PORT&gt;` to `./script/dev
31 Instructions for other systems 31 Instructions for other systems
32 ------------------------------ 32 ------------------------------
33 33
34 -On other OS, you have 2 options: 34 +On other OS, you have many options:
35 35
36 ### 1) using a chroot or a VM with Debian stable (easier) 36 ### 1) using a chroot or a VM with Debian stable (easier)
37 37
@@ -45,6 +45,14 @@ You can check `./script/install-dependencies/debian-squeeze.sh` to have an idea @@ -45,6 +45,14 @@ You can check `./script/install-dependencies/debian-squeeze.sh` to have an idea
45 45
46 If you write such script for your own OS, *please* share it with us at the development mailing list so that we can include it in the official repository. This way other people using the same OS will have to put less effort to develop Noosfero. 46 If you write such script for your own OS, *please* share it with us at the development mailing list so that we can include it in the official repository. This way other people using the same OS will have to put less effort to develop Noosfero.
47 47
  48 +### 3) Installing dependencies via Rubygems and RVM
  49 +
  50 +To setup the development environment through Rubygems you just need to install some basic deps and then install the gems defined on the Gemfile. Further instructions can be found on: http://noosfero.org/bin/view/Development/DepsWithRVMAndGems
  51 +
  52 +### 4) Using a docker image
  53 +
  54 +Use a docker image to run an out-of-the-box development environment. Further information can be found on: https://hub.docker.com/r/noosfero/dev-rails4/
  55 +
48 Submitting your changes back 56 Submitting your changes back
49 ---------------------------- 57 ----------------------------
50 58
app/api/entities.rb
@@ -38,9 +38,17 @@ module Api @@ -38,9 +38,17 @@ module Api
38 PERMISSIONS[current_permission] <= PERMISSIONS[permission] 38 PERMISSIONS[current_permission] <= PERMISSIONS[permission]
39 end 39 end
40 40
  41 + def self.expose_optional_field?(field, options = {})
  42 + return false if options[:params].nil?
  43 + optional_fields = options[:params][:optional_fields] || []
  44 + optional_fields.include?(field.to_s)
  45 + end
  46 +
  47 +
41 class Image < Entity 48 class Image < Entity
42 root 'images', 'image' 49 root 'images', 'image'
43 50
  51 + expose :filename
44 expose :url do |image, options| 52 expose :url do |image, options|
45 image.public_filename 53 image.public_filename
46 end 54 end
@@ -153,6 +161,9 @@ module Api @@ -153,6 +161,9 @@ module Api
153 expose :articles_count do |person, options| 161 expose :articles_count do |person, options|
154 person.articles.count 162 person.articles.count
155 end 163 end
  164 + expose :friends_count do |person, options|
  165 + person.friends.size
  166 + end
156 end 167 end
157 168
158 class Enterprise < Profile 169 class Enterprise < Profile
@@ -166,7 +177,8 @@ module Api @@ -166,7 +177,8 @@ module Api
166 community.admins.map{|admin| {"name"=>admin.name, "id"=>admin.id, "username" => admin.identifier}} 177 community.admins.map{|admin| {"name"=>admin.name, "id"=>admin.id, "username" => admin.identifier}}
167 end 178 end
168 expose :categories, :using => Category 179 expose :categories, :using => Category
169 - expose :members, :using => Person , :if => lambda{ |community, options| community.display_info_to? options[:current_person] } 180 + expose :members_count
  181 + expose :members, :if => lambda {|community, options| Entities.expose_optional_field?(:members, options)}
170 end 182 end
171 183
172 class CommentBase < Entity 184 class CommentBase < Entity
@@ -174,6 +186,10 @@ module Api @@ -174,6 +186,10 @@ module Api
174 expose :created_at, :format_with => :timestamp 186 expose :created_at, :format_with => :timestamp
175 expose :author, :using => Profile 187 expose :author, :using => Profile
176 expose :reply_of, :using => CommentBase 188 expose :reply_of, :using => CommentBase
  189 + expose :permissions do |comment, options|
  190 + Entities.permissions_for_entity(comment, options[:current_person],
  191 + :allow_destroy?)
  192 + end
177 end 193 end
178 194
179 class Comment < CommentBase 195 class Comment < CommentBase
@@ -209,7 +225,7 @@ module Api @@ -209,7 +225,7 @@ module Api
209 expose :comments_count 225 expose :comments_count
210 expose :archived, :documentation => {:type => "Boolean", :desc => "Defines if a article is readonly"} 226 expose :archived, :documentation => {:type => "Boolean", :desc => "Defines if a article is readonly"}
211 expose :type 227 expose :type
212 - expose :comments, using: CommentBase, :if => lambda{|obj,opt| opt[:params] && ['1','true',true].include?(opt[:params][:show_comments])} 228 + expose :comments, using: CommentBase, :if => lambda{|comment,options| Entities.expose_optional_field?(:comments, options)}
213 expose :published 229 expose :published
214 expose :accept_comments?, as: :accept_comments 230 expose :accept_comments?, as: :accept_comments
215 end 231 end
@@ -304,7 +320,7 @@ module Api @@ -304,7 +320,7 @@ module Api
304 end 320 end
305 expose :params, :if => lambda { |activity, options| activity.kind_of?(ActionTracker::Record)} 321 expose :params, :if => lambda { |activity, options| activity.kind_of?(ActionTracker::Record)}
306 expose :content, :if => lambda { |activity, options| activity.kind_of?(Scrap)} 322 expose :content, :if => lambda { |activity, options| activity.kind_of?(Scrap)}
307 - expose :verb do |activity, options| 323 + expose :verb do |activity, options|
308 activity.kind_of?(Scrap) ? 'leave_scrap' : activity.verb 324 activity.kind_of?(Scrap) ? 'leave_scrap' : activity.verb
309 end 325 end
310 326
app/api/helpers.rb
@@ -57,9 +57,11 @@ module Api @@ -57,9 +57,11 @@ module Api
57 def present_partial(model, options) 57 def present_partial(model, options)
58 if(params[:fields].present?) 58 if(params[:fields].present?)
59 begin 59 begin
60 - fields = JSON.parse(params[:fields]) 60 + fields = JSON.parse((params.to_hash[:fields] || params.to_hash['fields']).to_json)
61 if fields.present? 61 if fields.present?
62 - options.merge!(fields.symbolize_keys.slice(:only, :except)) 62 + fields = fields.symbolize_keys
  63 + options.merge!(:only => fields[:only]) if fields[:only].present?
  64 + options.merge!(:except => fields[:except]) if fields[:except].present?
63 end 65 end
64 rescue 66 rescue
65 fields = params[:fields] 67 fields = params[:fields]
@@ -116,7 +118,7 @@ module Api @@ -116,7 +118,7 @@ module Api
116 def post_article(asset, params) 118 def post_article(asset, params)
117 return forbidden! unless current_person.can_post_content?(asset) 119 return forbidden! unless current_person.can_post_content?(asset)
118 120
119 - klass_type = params[:content_type] || params[:article].delete(:type) || TinyMceArticle.name 121 + klass_type = params[:content_type] || params[:article].delete(:type) || TextArticle.name
120 return forbidden! unless klass_type.constantize <= Article 122 return forbidden! unless klass_type.constantize <= Article
121 123
122 article = klass_type.constantize.new(params[:article]) 124 article = klass_type.constantize.new(params[:article])
@@ -447,12 +449,12 @@ module Api @@ -447,12 +449,12 @@ module Api
447 end 449 end
448 450
449 def asset_with_image params 451 def asset_with_image params
450 - if params.has_key? :image_builder 452 + if !params.nil? && params.has_key?(:image_builder)
451 asset_api_params = params 453 asset_api_params = params
452 asset_api_params[:image_builder] = base64_to_uploadedfile(asset_api_params[:image_builder]) 454 asset_api_params[:image_builder] = base64_to_uploadedfile(asset_api_params[:image_builder])
453 return asset_api_params 455 return asset_api_params
454 end 456 end
455 - params 457 + params
456 end 458 end
457 459
458 def base64_to_uploadedfile(base64_image) 460 def base64_to_uploadedfile(base64_image)
@@ -503,11 +505,9 @@ module Api @@ -503,11 +505,9 @@ module Api
503 505
504 def parse_content_type(content_type) 506 def parse_content_type(content_type)
505 return nil if content_type.blank? 507 return nil if content_type.blank?
506 - content_types = content_type.split(',').map do |content_type|  
507 - content_type = content_type.camelcase  
508 - content_type == 'TextArticle' ? Article.text_article_types : content_type 508 + content_type.split(',').map do |content_type|
  509 + content_type.camelcase
509 end 510 end
510 - content_types.flatten.uniq  
511 end 511 end
512 512
513 def period(from_date, until_date) 513 def period(from_date, until_date)
app/api/v1/articles.rb
@@ -284,7 +284,7 @@ module Api @@ -284,7 +284,7 @@ module Api
284 284
285 if params[:path].present? 285 if params[:path].present?
286 article = profile.articles.find_by path: params[:path] 286 article = profile.articles.find_by path: params[:path]
287 - if !article || !article.display_to?(current_person) 287 + if article && !article.display_to?(current_person)
288 article = forbidden! 288 article = forbidden!
289 end 289 end
290 290
app/api/v1/blocks.rb
@@ -6,6 +6,7 @@ module Api @@ -6,6 +6,7 @@ module Api
6 get ':id' do 6 get ':id' do
7 block = Block.find(params["id"]) 7 block = Block.find(params["id"])
8 return forbidden! unless block.visible_to_user?(current_person) || block.allow_edit?(current_person) 8 return forbidden! unless block.visible_to_user?(current_person) || block.allow_edit?(current_person)
  9 + block.api_content_params = params.except("id")
9 present block, :with => Entities::Block, display_api_content: true, current_person: current_person 10 present block, :with => Entities::Block, display_api_content: true, current_person: current_person
10 end 11 end
11 12
app/api/v1/communities.rb
@@ -18,7 +18,7 @@ module Api @@ -18,7 +18,7 @@ module Api
18 communities = select_filtered_collection_of(environment, 'communities', params) 18 communities = select_filtered_collection_of(environment, 'communities', params)
19 communities = profiles_for_person(communities, current_person) 19 communities = profiles_for_person(communities, current_person)
20 communities = communities.by_location(params) # Must be the last. May return Exception obj 20 communities = communities.by_location(params) # Must be the last. May return Exception obj
21 - present communities, :with => Entities::Community, :current_person => current_person 21 + present communities, :with => Entities::Community, :current_person => current_person, :params => params
22 end 22 end
23 23
24 24
@@ -49,7 +49,7 @@ module Api @@ -49,7 +49,7 @@ module Api
49 49
50 get ':id' do 50 get ':id' do
51 community = profiles_for_person(environment.communities, current_person).find_by_id(params[:id]) 51 community = profiles_for_person(environment.communities, current_person).find_by_id(params[:id])
52 - present community, :with => Entities::Community, :current_person => current_person 52 + present community, :with => Entities::Community, :current_person => current_person, :params => params
53 end 53 end
54 54
55 end 55 end
app/api/v1/profiles.rb
@@ -28,7 +28,7 @@ module Api @@ -28,7 +28,7 @@ module Api
28 authenticate! 28 authenticate!
29 profile = environment.profiles.find_by(id: params[:id]) 29 profile = environment.profiles.find_by(id: params[:id])
30 return forbidden! unless profile.allow_edit?(current_person) 30 return forbidden! unless profile.allow_edit?(current_person)
31 - profile.update_attributes!(params[:profile]) 31 + profile.update_attributes!(asset_with_image(params[:profile]))
32 present profile, :with => Entities::Profile, :current_person => current_person 32 present profile, :with => Entities::Profile, :current_person => current_person
33 end 33 end
34 34
app/api/v1/session.rb
@@ -174,14 +174,13 @@ module Api @@ -174,14 +174,13 @@ module Api
174 # Example Request: 174 # Example Request:
175 # PATCH /new_password?code=xxxx&password=secret&password_confirmation=secret 175 # PATCH /new_password?code=xxxx&password=secret&password_confirmation=secret
176 patch "/new_password" do 176 patch "/new_password" do
177 - change_password = ChangePassword.find_by code: params[:code]  
178 - not_found! if change_password.nil?  
179 -  
180 - if change_password.update_attributes(:password => params[:password], :password_confirmation => params[:password_confirmation]) 177 + begin
  178 + change_password = ChangePassword.find_by! code: params[:code]
  179 + change_password.update_attributes!(:password => params[:password], :password_confirmation => params[:password_confirmation])
181 change_password.finish 180 change_password.finish
182 present change_password.requestor.user, :with => Entities::UserLogin, :current_person => current_person 181 present change_password.requestor.user, :with => Entities::UserLogin, :current_person => current_person
183 - else  
184 - something_wrong! 182 + rescue Exception => ex
  183 + render_api_error!(ex.message, 400)
185 end 184 end
186 end 185 end
187 186
app/controllers/my_profile/cms_controller.rb
@@ -146,11 +146,14 @@ class CmsController &lt; MyProfileController @@ -146,11 +146,14 @@ class CmsController &lt; MyProfileController
146 parent = check_parent(params[:parent_id]) 146 parent = check_parent(params[:parent_id])
147 if parent 147 if parent
148 @article.parent = parent 148 @article.parent = parent
  149 + @article.published = parent.published
  150 + @article.show_to_followers = parent.show_to_followers
149 @parent_id = parent.id 151 @parent_id = parent.id
150 end 152 end
151 153
152 @article.profile = profile 154 @article.profile = profile
153 @article.author = user 155 @article.author = user
  156 + @article.editor = current_person.editor
154 @article.last_changed_by = user 157 @article.last_changed_by = user
155 @article.created_by = user 158 @article.created_by = user
156 159
@@ -399,8 +402,7 @@ class CmsController &lt; MyProfileController @@ -399,8 +402,7 @@ class CmsController &lt; MyProfileController
399 402
400 def available_article_types 403 def available_article_types
401 articles = [ 404 articles = [
402 - TinyMceArticle,  
403 - TextileArticle, 405 + TextArticle,
404 Event 406 Event
405 ] 407 ]
406 articles += special_article_types if params && params[:cms] 408 articles += special_article_types if params && params[:cms]
@@ -408,9 +410,6 @@ class CmsController &lt; MyProfileController @@ -408,9 +410,6 @@ class CmsController &lt; MyProfileController
408 if @parent && @parent.blog? 410 if @parent && @parent.blog?
409 articles -= Article.folder_types.map(&:constantize) 411 articles -= Article.folder_types.map(&:constantize)
410 end 412 end
411 - if user.is_admin?(profile.environment)  
412 - articles << RawHTMLArticle  
413 - end  
414 articles 413 articles
415 end 414 end
416 415
app/controllers/my_profile/profile_editor_controller.rb
@@ -12,7 +12,7 @@ class ProfileEditorController &lt; MyProfileController @@ -12,7 +12,7 @@ class ProfileEditorController &lt; MyProfileController
12 include CategoriesHelper 12 include CategoriesHelper
13 13
14 def index 14 def index
15 - @pending_tasks = Task.to(profile).pending.without_spam.select{|i| user.has_permission?(i.permission, profile)} 15 + @pending_tasks = Task.to(profile).pending.without_spam
16 @show_appearance_option = user.is_admin?(environment) || environment.enabled?('enable_appearance') 16 @show_appearance_option = user.is_admin?(environment) || environment.enabled?('enable_appearance')
17 @show_header_footer_option = user.is_admin?(environment) || (!profile.enterprise? && !environment.enabled?('disable_header_and_footer')) 17 @show_header_footer_option = user.is_admin?(environment) || (!profile.enterprise? && !environment.enabled?('disable_header_and_footer'))
18 end 18 end
@@ -95,7 +95,7 @@ class ProfileEditorController &lt; MyProfileController @@ -95,7 +95,7 @@ class ProfileEditorController &lt; MyProfileController
95 end 95 end
96 96
97 def welcome_page 97 def welcome_page
98 - @welcome_page = profile.welcome_page || TinyMceArticle.new(:name => 'Welcome Page', :profile => profile, :published => false) 98 + @welcome_page = profile.welcome_page || TextArticle.new(:name => 'Welcome Page', :profile => profile, :published => false)
99 if request.post? 99 if request.post?
100 begin 100 begin
101 @welcome_page.update!(params[:welcome_page]) 101 @welcome_page.update!(params[:welcome_page])
app/controllers/public/account_controller.rb
@@ -164,6 +164,7 @@ class AccountController &lt; ApplicationController @@ -164,6 +164,7 @@ class AccountController &lt; ApplicationController
164 def logout 164 def logout
165 if logged_in? 165 if logged_in?
166 self.current_user.forget_me 166 self.current_user.forget_me
  167 + current_user.update({:chat_status_at => DateTime.now}.merge({:last_chat_status => current_user.chat_status, :chat_status => 'offline'}))
167 end 168 end
168 reset_session 169 reset_session
169 session[:notice] = _("You have been logged out.") 170 session[:notice] = _("You have been logged out.")
app/controllers/public/chat_controller.rb
@@ -113,8 +113,20 @@ class ChatController &lt; PublicController @@ -113,8 +113,20 @@ class ChatController &lt; PublicController
113 end 113 end
114 114
115 #TODO Ideally this is done through roster table on ejabberd. 115 #TODO Ideally this is done through roster table on ejabberd.
116 - def roster_groups  
117 - render :text => user.memberships.map {|m| {:jid => m.jid, :name => m.name}}.to_json 116 + def rosters
  117 + rooms = user.memberships.map {|m| {:jid => m.jid, :name => m.name}}
  118 + friends = user.friends.map {|f| {:jid => f.jid, :name => f.name}}
  119 + rosters = {:rooms => rooms, :friends => friends}
  120 + render :text => rosters.to_json
  121 + end
  122 +
  123 + def availabilities
  124 + availabilities = user.friends.map do |friend|
  125 + status = friend.user.chat_status
  126 + status = 'offline' if status.blank?
  127 + {:jid => friend.jid, :status => status}
  128 + end
  129 + render :text => availabilities.to_json
118 end 130 end
119 131
120 protected 132 protected
app/controllers/public/invite_controller.rb
@@ -98,6 +98,8 @@ class InviteController &lt; PublicController @@ -98,6 +98,8 @@ class InviteController &lt; PublicController
98 scope = profile.invite_friends_only ? user.friends : environment.people 98 scope = profile.invite_friends_only ? user.friends : environment.people
99 scope = scope.not_members_of(profile) if profile.organization? 99 scope = scope.not_members_of(profile) if profile.organization?
100 scope = scope.not_friends_of(profile) if profile.person? 100 scope = scope.not_friends_of(profile) if profile.person?
  101 + scope = scope.distinct(false).group("profiles.id")
  102 +
101 results = find_by_contents(:people, environment, scope, params['q'], {:page => 1}, {:joins => :user})[:results] 103 results = find_by_contents(:people, environment, scope, params['q'], {:page => 1}, {:joins => :user})[:results]
102 render :text => prepare_to_token_input(results).to_json 104 render :text => prepare_to_token_input(results).to_json
103 end 105 end
app/controllers/public/profile_controller.rb
@@ -13,12 +13,13 @@ class ProfileController &lt; PublicController @@ -13,12 +13,13 @@ class ProfileController &lt; PublicController
13 13
14 protect 'send_mail_to_members', :profile, :only => [:send_mail] 14 protect 'send_mail_to_members', :profile, :only => [:send_mail]
15 15
  16 + ACTIVITIES_PER_PAGE = 15
  17 +
16 def index 18 def index
17 - @network_activities = !@profile.is_a?(Person) ? @profile.tracked_notifications.visible.paginate(:per_page => 15, :page => params[:page]) : []  
18 - if logged_in? && current_person.follows?(@profile)  
19 - @network_activities = @profile.tracked_notifications.visible.paginate(:per_page => 15, :page => params[:page]) if @network_activities.empty?  
20 - @activities = @profile.activities.paginate(:per_page => 15, :page => params[:page])  
21 - end 19 + @offsets = {:wall => 0, :network => 0}
  20 + page = (params[:page] || 1).to_i
  21 + @network_activities = loop_fetch_activities(@profile.tracked_notifications, :network, page) if !@profile.is_a?(Person) || follow_profile?
  22 + @activities = loop_fetch_activities(@profile.activities, :wall, page) if follow_profile?
22 @tags = profile.article_tags 23 @tags = profile.article_tags
23 allow_access_to_page 24 allow_access_to_page
24 end 25 end
@@ -231,6 +232,7 @@ class ProfileController &lt; PublicController @@ -231,6 +232,7 @@ class ProfileController &lt; PublicController
231 @scrap = Scrap.new(params[:scrap]) 232 @scrap = Scrap.new(params[:scrap])
232 @scrap.sender= sender 233 @scrap.sender= sender
233 @scrap.receiver= receiver 234 @scrap.receiver= receiver
  235 + @scrap.marked_people = treat_followed_entries(params[:filter_followed])
234 @tab_action = params[:tab_action] 236 @tab_action = params[:tab_action]
235 @message = @scrap.save ? _("Message successfully sent.") : _("You can't leave an empty message.") 237 @message = @scrap.save ? _("Message successfully sent.") : _("You can't leave an empty message.")
236 activities = @profile.activities.paginate(:per_page => 15, :page => params[:page]) if params[:not_load_scraps].nil? 238 activities = @profile.activities.paginate(:per_page => 15, :page => params[:page]) if params[:not_load_scraps].nil?
@@ -249,18 +251,44 @@ class ProfileController &lt; PublicController @@ -249,18 +251,44 @@ class ProfileController &lt; PublicController
249 render :partial => 'profile_activities_list', :locals => {:activities => activities} 251 render :partial => 'profile_activities_list', :locals => {:activities => activities}
250 else 252 else
251 network_activities = @profile.tracked_notifications.visible.paginate(:per_page => 15, :page => params[:page]) 253 network_activities = @profile.tracked_notifications.visible.paginate(:per_page => 15, :page => params[:page])
252 - render :partial => 'profile_network_activities', :locals => {:network_activities => network_activities} 254 + render :partial => 'profile_network_activities', :locals => {:activities => network_activities}
253 end 255 end
254 end 256 end
255 257
256 - def view_more_activities  
257 - @activities = @profile.activities.paginate(:per_page => 10, :page => params[:page])  
258 - render :partial => 'profile_activities_list', :locals => {:activities => @activities} 258 + def search_followed
  259 + result = []
  260 + circles = find_by_contents(:circles, user, user.circles.where(:profile_type => 'Person'), params[:q])[:results]
  261 + followed = find_by_contents(:followed, user, Profile.followed_by(user), params[:q])[:results]
  262 + result = circles + followed
  263 + render :text => prepare_to_token_input_by_class(result).to_json
259 end 264 end
260 265
261 - def view_more_network_activities  
262 - @activities = @profile.tracked_notifications.paginate(:per_page => 10, :page => params[:page])  
263 - render :partial => 'profile_network_activities', :locals => {:network_activities => @activities} 266 + def loop_fetch_activities(base_activities, kind, page)
  267 + activities = nil
  268 + while activities.nil? || (activities.empty? && page <= activities.total_pages)
  269 + activities = base_activities.offset(@offsets[kind.to_sym]).paginate(:per_page => ACTIVITIES_PER_PAGE, :page => page)
  270 + activities = filter_activities(activities, kind.to_sym)
  271 + page += 1
  272 + end
  273 + activities
  274 + end
  275 +
  276 + def view_more_activities
  277 + @activities = nil
  278 + @offsets = params[:offsets]
  279 + page = (params[:page] || 1).to_i
  280 + kind = params[:kind]
  281 +
  282 + if kind == 'wall'
  283 + base_activities = @profile.activities
  284 + partial = 'profile_activities_list'
  285 + else
  286 + base_activities = @profile.tracked_notifications
  287 + partial = 'profile_network_activities'
  288 + end
  289 +
  290 + @activities = loop_fetch_activities(base_activities, kind, page)
  291 + render :partial => partial, :locals => {:activities => @activities}
264 end 292 end
265 293
266 def more_comments 294 def more_comments
@@ -434,7 +462,6 @@ class ProfileController &lt; PublicController @@ -434,7 +462,6 @@ class ProfileController &lt; PublicController
434 end 462 end
435 end 463 end
436 464
437 -  
438 protected 465 protected
439 466
440 def check_access_to_profile 467 def check_access_to_profile
@@ -480,4 +507,39 @@ class ProfileController &lt; PublicController @@ -480,4 +507,39 @@ class ProfileController &lt; PublicController
480 render_not_found unless profile.allow_followers? 507 render_not_found unless profile.allow_followers?
481 end 508 end
482 509
  510 + def treat_followed_entries(entries)
  511 + return [] if entries.blank? || profile != user
  512 +
  513 + followed = []
  514 + entries.split(',').map do |entry|
  515 + klass, identifier = entry.split('_')
  516 + case klass
  517 + when 'Person'
  518 + followed << Person.find(identifier)
  519 + when 'Circle'
  520 + circle = Circle.find(identifier)
  521 + followed += Profile.in_circle(circle)
  522 + end
  523 + end
  524 + followed.uniq
  525 + end
  526 +
  527 + def filter_activities(activities, kind)
  528 + @offsets ||= {:wall => 0, :network => 0}
  529 + return activities if environment.admins.include?(user)
  530 + activities = Array(activities)
  531 + initial_count = activities.count
  532 + activities.delete_if do |activity|
  533 + activity = ActivityPresenter.for(activity)
  534 + next if activity.involved?(user)
  535 + activity.hidden_for?(user)
  536 + end
  537 + @offsets[kind] = @offsets[kind].to_i
  538 + @offsets[kind] += initial_count - activities.count
  539 + activities
  540 + end
  541 +
  542 + def follow_profile?
  543 + logged_in? && current_person.follows?(@profile)
  544 + end
483 end 545 end
app/helpers/application_helper.rb
@@ -111,10 +111,6 @@ module ApplicationHelper @@ -111,10 +111,6 @@ module ApplicationHelper
111 content = capture(&block) 111 content = capture(&block)
112 end 112 end
113 113
114 - if options[:type] == :textile  
115 - content = RedCloth.new(content).to_html  
116 - end  
117 -  
118 options[:class] = '' if ! options[:class] 114 options[:class] = '' if ! options[:class]
119 options[:class] += ' button icon-help' # with-text 115 options[:class] += ' button icon-help' # with-text
120 116
@@ -132,13 +128,6 @@ module ApplicationHelper @@ -132,13 +128,6 @@ module ApplicationHelper
132 text 128 text
133 end 129 end
134 130
135 - # alias for <tt>help(content, :textile)</tt>. You can pass a block in the  
136 - # same way you would do if you called <tt>help</tt> directly.  
137 - def help_textile(content = nil, link_name = nil, options = {}, &block)  
138 - options[:type] = :textile  
139 - help(content, link_name, options, &block)  
140 - end  
141 -  
142 # TODO: do something more useful here 131 # TODO: do something more useful here
143 # TODO: test this helper 132 # TODO: test this helper
144 # TODO: add an icon? 133 # TODO: add an icon?
@@ -531,8 +520,6 @@ module ApplicationHelper @@ -531,8 +520,6 @@ module ApplicationHelper
531 html = "\n" 520 html = "\n"
532 values.each { |val, h_val| 521 values.each { |val, h_val|
533 id = object_name.to_s() +'_'+ method.to_s() +'_'+ val.to_s() 522 id = object_name.to_s() +'_'+ method.to_s() +'_'+ val.to_s()
534 - # Não está apresentando o sexo selecionado ao revisitar  
535 - # http://localhost:3000/myprofile/manuel/profile_editor/edit :-(  
536 html += self.class.content_tag( 'span', 523 html += self.class.content_tag( 'span',
537 @template.radio_button( object_name, method, val, 524 @template.radio_button( object_name, method, val,
538 :id => id, :object => @object ) + 525 :id => id, :object => @object ) +
@@ -543,6 +530,7 @@ module ApplicationHelper @@ -543,6 +530,7 @@ module ApplicationHelper
543 html += "<br />\n".html_safe 530 html += "<br />\n".html_safe
544 end 531 end
545 } 532 }
  533 + html = html.html_safe
546 html += "<br />\n".html_safe if line_size == 0 || ( values.size % line_size ) > 0 534 html += "<br />\n".html_safe if line_size == 0 || ( values.size % line_size ) > 0
547 column = object.class.columns_hash[method.to_s] if object 535 column = object.class.columns_hash[method.to_s] if object
548 text = 536 text =
@@ -552,7 +540,7 @@ module ApplicationHelper @@ -552,7 +540,7 @@ module ApplicationHelper
552 ) 540 )
553 label_html = self.class.content_tag 'label', text, 541 label_html = self.class.content_tag 'label', text,
554 :class => 'formlabel' 542 :class => 'formlabel'
555 - control_html = self.class.content_tag 'div', html, 543 + control_html = self.class.content_tag 'div', html.html_safe,
556 :class => 'formfield type-radio '+ 544 :class => 'formfield type-radio '+
557 'fieldgroup linesize'+line_size.to_s() 545 'fieldgroup linesize'+line_size.to_s()
558 546
@@ -977,11 +965,16 @@ module ApplicationHelper @@ -977,11 +965,16 @@ module ApplicationHelper
977 content_tag(:div, _('Source: %s') % source_url, :id => 'article-source') unless source_url.nil? 965 content_tag(:div, _('Source: %s') % source_url, :id => 'article-source') unless source_url.nil?
978 end 966 end
979 967
980 - def task_information(task) 968 + def task_information(task, params = {})
981 values = {} 969 values = {}
982 values.merge!(task.information[:variables]) if task.information[:variables] 970 values.merge!(task.information[:variables]) if task.information[:variables]
983 values.merge!({:requestor => link_to(task.requestor.name, task.requestor.url)}) if task.requestor 971 values.merge!({:requestor => link_to(task.requestor.name, task.requestor.url)}) if task.requestor
984 - values.merge!({:target => link_to(task.target.name, task.target.url)}) if (task.target && task.target.respond_to?(:url)) 972 + if (task.target && task.target.respond_to?(:url))
  973 + values.merge!({:target => link_to(task.target.name, task.target.url)})
  974 + target_detail = _("in %s").html_safe % values[:target]
  975 + target_detail = '' if task.target.identifier == params[:profile]
  976 + values.merge!({:target_detail => target_detail})
  977 + end
985 values.merge!({:subject => content_tag('span', task.subject, :class=>'task_target')}) if task.subject 978 values.merge!({:subject => content_tag('span', task.subject, :class=>'task_target')}) if task.subject
986 values.merge!({:linked_subject => link_to(content_tag('span', task.linked_subject[:text], :class => 'task_target'), task.linked_subject[:url])}) if task.linked_subject 979 values.merge!({:linked_subject => link_to(content_tag('span', task.linked_subject[:text], :class => 'task_target'), task.linked_subject[:url])}) if task.linked_subject
987 (task.information[:message] % values).html_safe 980 (task.information[:message] % values).html_safe
@@ -992,8 +985,8 @@ module ApplicationHelper @@ -992,8 +985,8 @@ module ApplicationHelper
992 end 985 end
993 986
994 def add_zoom_to_images 987 def add_zoom_to_images
995 - stylesheet_link_tag('jquery.fancybox') +  
996 - javascript_include_tag('jquery.fancybox.pack') + 988 + stylesheet_link_tag('vendor/jquery.fancybox') +
  989 + javascript_include_tag('vendor/jquery.fancybox.pack') +
997 javascript_tag("apply_zoom_to_images(#{_('Zoom in').to_json})") 990 javascript_tag("apply_zoom_to_images(#{_('Zoom in').to_json})")
998 end 991 end
999 992
@@ -1185,10 +1178,10 @@ module ApplicationHelper @@ -1185,10 +1178,10 @@ module ApplicationHelper
1185 end 1178 end
1186 1179
1187 controller_target = suggestion.suggestion_type == 'Person' ? :friends : :memberships 1180 controller_target = suggestion.suggestion_type == 'Person' ? :friends : :memberships
1188 - profiles << link_to("<big> +#{suggestion.profile_connections.count - 4}</big>", :controller => controller_target, :action => :connections, :id => suggestion.suggestion_id) if suggestion.profile_connections.count > 4 1181 + profiles << link_to("<big> +#{suggestion.profile_connections.count - 4}</big>".html_safe, :controller => controller_target, :action => :connections, :id => suggestion.suggestion_id) if suggestion.profile_connections.count > 4
1189 1182
1190 if profiles.present? 1183 if profiles.present?
1191 - content_tag(:div, profiles.join , :class => 'profile-connections') 1184 + content_tag(:div, profiles.safe_join , :class => 'profile-connections')
1192 else 1185 else
1193 '' 1186 ''
1194 end 1187 end
@@ -1245,4 +1238,15 @@ module ApplicationHelper @@ -1245,4 +1238,15 @@ module ApplicationHelper
1245 content.html_safe 1238 content.html_safe
1246 end 1239 end
1247 1240
  1241 + def current_editor_is?(editor)
  1242 + editor.blank? ? false : current_editor == editor
  1243 + end
  1244 +
  1245 + def current_editor(mode = '')
  1246 + editor = @article.editor || Article::Editor::TINY_MCE unless @article.nil?
  1247 + editor ||= (current_person.nil? || current_person.editor.nil?) ? Article::Editor::TINY_MCE : current_person.editor
  1248 + editor += '_' + mode unless mode.blank?
  1249 + editor
  1250 + end
  1251 +
1248 end 1252 end
app/helpers/article_helper.rb
@@ -61,7 +61,9 @@ module ArticleHelper @@ -61,7 +61,9 @@ module ArticleHelper
61 'div', 61 'div',
62 check_box(:article, :display_versions) + 62 check_box(:article, :display_versions) +
63 content_tag('label', _('I want this article to display a link to older versions'), :for => 'article_display_versions') 63 content_tag('label', _('I want this article to display a link to older versions'), :for => 'article_display_versions')
64 - ) : '') 64 + ) : '') +
  65 +
  66 + (self.respond_to?(:extra_options) ? self.extra_options : "")
65 ) 67 )
66 end 68 end
67 69
@@ -161,6 +163,10 @@ module ArticleHelper @@ -161,6 +163,10 @@ module ArticleHelper
161 array.map { |object| {:label => object.name, :value => object.name} } 163 array.map { |object| {:label => object.name, :value => object.name} }
162 end 164 end
163 165
  166 + def prepare_to_token_input_by_class(array)
  167 + array.map { |object| {:id => "#{object.class.name}_#{object.id || object.name}", :name => "#{object.name} (#{_(object.class.name)})", :class => object.class.name}}
  168 + end
  169 +
164 def cms_label_for_new_children 170 def cms_label_for_new_children
165 _('New article') 171 _('New article')
166 end 172 end
app/helpers/chat_helper.rb
@@ -14,7 +14,7 @@ module ChatHelper @@ -14,7 +14,7 @@ module ChatHelper
14 :class => icon_class + ' simplemenu-trigger' 14 :class => icon_class + ' simplemenu-trigger'
15 ) + 15 ) +
16 content_tag('ul', 16 content_tag('ul',
17 - links.map{|link| content_tag('li', link_to(link[1], '', :class => link[0], :id => link[2], 'data-jid' => user.jid), :class => 'simplemenu-item') }.join("\n"), 17 + links.map{|link| content_tag('li', link_to(link[1], '', :class => link[0], :id => link[2], 'data-jid' => user.jid), :class => 'simplemenu-item') }.join("\n").html_safe,
18 :style => 'display: none; z-index: 100', 18 :style => 'display: none; z-index: 100',
19 :class => 'simplemenu-submenu' 19 :class => 'simplemenu-submenu'
20 ), 20 ),
app/helpers/email_template_helper.rb
@@ -6,7 +6,7 @@ module EmailTemplateHelper @@ -6,7 +6,7 @@ module EmailTemplateHelper
6 params[:subject] = params[:email_template].parsed_subject(params[:template_params]) 6 params[:subject] = params[:email_template].parsed_subject(params[:template_params])
7 params[:content_type] = "text/html" 7 params[:content_type] = "text/html"
8 end 8 end
9 - mail(params.except(:email_template)) 9 + mail(params.except(:email_template, :template_params))
10 end 10 end
11 11
12 end 12 end
app/helpers/gallery_helper.rb 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +module GalleryHelper
  2 +
  3 + include ArticleHelper
  4 +
  5 + def extra_options
  6 + content_tag(
  7 + 'div',
  8 + check_box(:article, :allow_download) +
  9 + content_tag('label', _('Allow images from this gallery to be downloaded'), :for => 'article_allow_download')
  10 + )
  11 + end
  12 +
  13 +end
app/helpers/profile_editor_helper.rb
@@ -158,4 +158,8 @@ module ProfileEditorHelper @@ -158,4 +158,8 @@ module ProfileEditorHelper
158 end 158 end
159 end 159 end
160 160
  161 + def select_editor(title, object, method, options)
  162 + labelled_form_field(title, select(object, method, current_person.available_editors.map { |k,v| [v, k] }))
  163 + end
  164 +
161 end 165 end
app/helpers/search_helper.rb
@@ -45,7 +45,8 @@ module SearchHelper @@ -45,7 +45,8 @@ module SearchHelper
45 def search_page_title(title, category = nil) 45 def search_page_title(title, category = nil)
46 title = "<h1>" + title 46 title = "<h1>" + title
47 title += ' - <small>' + category.name + '</small>' if category 47 title += ' - <small>' + category.name + '</small>' if category
48 - title + "</h1>" 48 + title += "</h1>"
  49 + title.html_safe
49 end 50 end
50 51
51 def category_context(category, url) 52 def category_context(category, url)
app/helpers/tags_helper.rb
@@ -67,4 +67,17 @@ module TagsHelper @@ -67,4 +67,17 @@ module TagsHelper
67 end.join("\n").html_safe 67 end.join("\n").html_safe
68 end 68 end
69 69
  70 + def linked_article_tags(article)
  71 + if @profile
  72 + # We are rendering a page inside a profile, so link to the profile tag search.
  73 + url = { :controller => 'profile', :profile => @profile.identifier, :action => 'tags' }
  74 + tagname_option = :id
  75 + else
  76 + # We are rendering a page outside a profile, so link to the global tag search.
  77 + url = { :action => 'tag' }
  78 + tagname_option = :tag
  79 + end
  80 + article.tags.map { |t| link_to(t, url.merge(tagname_option=>t.name) ) }.join("\n")
  81 + end
  82 +
70 end 83 end
app/helpers/tinymce_helper.rb
@@ -18,7 +18,8 @@ module TinymceHelper @@ -18,7 +18,8 @@ module TinymceHelper
18 insertdatetime media nonbreaking save table contextmenu directionality 18 insertdatetime media nonbreaking save table contextmenu directionality
19 emoticons template paste textcolor colorpicker textpattern], 19 emoticons template paste textcolor colorpicker textpattern],
20 :image_advtab => true, 20 :image_advtab => true,
21 - :language => tinymce_language 21 + :language => tinymce_language,
  22 + :selector => '.' + current_editor(options[:mode])
22 23
23 options[:toolbar1] = toolbar1(options[:mode]) 24 options[:toolbar1] = toolbar1(options[:mode])
24 options[:menubar] = menubar(options[:mode]) 25 options[:menubar] = menubar(options[:mode])
app/helpers/token_helper.rb
@@ -5,10 +5,11 @@ module TokenHelper @@ -5,10 +5,11 @@ module TokenHelper
5 end 5 end
6 6
7 def token_input_field_tag(name, element_id, search_action, options = {}, text_field_options = {}, html_options = {}) 7 def token_input_field_tag(name, element_id, search_action, options = {}, text_field_options = {}, html_options = {})
8 - options[:min_chars] ||= 3 8 + options[:min_chars] ||= 2
9 options[:hint_text] ||= _("Type in a search term") 9 options[:hint_text] ||= _("Type in a search term")
10 options[:no_results_text] ||= _("No results") 10 options[:no_results_text] ||= _("No results")
11 options[:searching_text] ||= _("Searching...") 11 options[:searching_text] ||= _("Searching...")
  12 + options[:placeholder] ||= 'null'
12 options[:search_delay] ||= 1000 13 options[:search_delay] ||= 1000
13 options[:prevent_duplicates] ||= true 14 options[:prevent_duplicates] ||= true
14 options[:backspace_delete_item] ||= false 15 options[:backspace_delete_item] ||= false
@@ -20,6 +21,9 @@ module TokenHelper @@ -20,6 +21,9 @@ module TokenHelper
20 options[:on_delete] ||= 'null' 21 options[:on_delete] ||= 'null'
21 options[:on_ready] ||= 'null' 22 options[:on_ready] ||= 'null'
22 options[:query_param] ||= 'q' 23 options[:query_param] ||= 'q'
  24 + options[:theme] ||= 'null'
  25 + options[:results_formatter] ||= 'null'
  26 + options[:token_formatter] ||= 'null'
23 27
24 result = text_field_tag(name, nil, text_field_options.merge(html_options.merge({:id => element_id}))) 28 result = text_field_tag(name, nil, text_field_options.merge(html_options.merge({:id => element_id})))
25 result += javascript_tag("jQuery('##{element_id}') 29 result += javascript_tag("jQuery('##{element_id}')
@@ -29,6 +33,7 @@ module TokenHelper @@ -29,6 +33,7 @@ module TokenHelper
29 hintText: #{options[:hint_text].to_json}, 33 hintText: #{options[:hint_text].to_json},
30 noResultsText: #{options[:no_results_text].to_json}, 34 noResultsText: #{options[:no_results_text].to_json},
31 searchingText: #{options[:searching_text].to_json}, 35 searchingText: #{options[:searching_text].to_json},
  36 + placeholder: #{options[:placeholder].to_json},
32 searchDelay: #{options[:search_delay].to_json}, 37 searchDelay: #{options[:search_delay].to_json},
33 preventDuplicates: #{options[:prevent_duplicates].to_json}, 38 preventDuplicates: #{options[:prevent_duplicates].to_json},
34 backspaceDeleteItem: #{options[:backspace_delete_item].to_json}, 39 backspaceDeleteItem: #{options[:backspace_delete_item].to_json},
@@ -39,6 +44,9 @@ module TokenHelper @@ -39,6 +44,9 @@ module TokenHelper
39 onAdd: #{options[:on_add]}, 44 onAdd: #{options[:on_add]},
40 onDelete: #{options[:on_delete]}, 45 onDelete: #{options[:on_delete]},
41 onReady: #{options[:on_ready]}, 46 onReady: #{options[:on_ready]},
  47 + theme: #{options[:theme] == 'null' ? options[:theme] : options[:theme].to_json},
  48 + resultsFormater: #{options[:results_formatter]},
  49 + tokenFormater: #{options[:token_formatter]},
42 }); 50 });
43 ") 51 ")
44 result += javascript_tag("jQuery('##{element_id}').focus();") if options[:focus] 52 result += javascript_tag("jQuery('##{element_id}').focus();") if options[:focus]
app/jobs/notify_activity_to_profiles_job.rb
@@ -11,7 +11,7 @@ class NotifyActivityToProfilesJob &lt; Struct.new(:tracked_action_id) @@ -11,7 +11,7 @@ class NotifyActivityToProfilesJob &lt; Struct.new(:tracked_action_id)
11 tracked_action = ActionTracker::Record.find(tracked_action_id) 11 tracked_action = ActionTracker::Record.find(tracked_action_id)
12 return unless tracked_action.user.present? 12 return unless tracked_action.user.present?
13 target = tracked_action.target 13 target = tracked_action.target
14 - if target.is_a?(Community) && ( NOTIFY_ONLY_COMMUNITY.include?(tracked_action.verb) || ! target.public_profile ) 14 + if target.is_a?(Community) && NOTIFY_ONLY_COMMUNITY.include?(tracked_action.verb)
15 ActionTrackerNotification.create(:profile_id => target.id, :action_tracker_id => tracked_action.id) 15 ActionTrackerNotification.create(:profile_id => target.id, :action_tracker_id => tracked_action.id)
16 return 16 return
17 end 17 end
@@ -19,8 +19,13 @@ class NotifyActivityToProfilesJob &lt; Struct.new(:tracked_action_id) @@ -19,8 +19,13 @@ class NotifyActivityToProfilesJob &lt; Struct.new(:tracked_action_id)
19 # Notify the user 19 # Notify the user
20 ActionTrackerNotification.create(:profile_id => tracked_action.user.id, :action_tracker_id => tracked_action.id) 20 ActionTrackerNotification.create(:profile_id => tracked_action.user.id, :action_tracker_id => tracked_action.id)
21 21
22 - # Notify all followers  
23 - ActionTrackerNotification.connection.execute("INSERT INTO action_tracker_notifications(profile_id, action_tracker_id) SELECT DISTINCT c.person_id, #{tracked_action.id} FROM profiles_circles AS p JOIN circles as c ON c.id = p.circle_id WHERE p.profile_id = #{tracked_action.user.id} AND (c.person_id NOT IN (SELECT atn.profile_id FROM action_tracker_notifications AS atn WHERE atn.action_tracker_id = #{tracked_action.id}))") 22 + if target.is_a?(Scrap) && target.marked_people.present?
  23 + # Notify only marked people
  24 + ActionTrackerNotification.connection.execute("INSERT INTO action_tracker_notifications(profile_id, action_tracker_id) SELECT DISTINCT profiles.id, #{tracked_action.id} FROM profiles WHERE profiles.id IN (#{target.marked_people.map(&:id).join(',')})")
  25 + else
  26 + # Notify all followers
  27 + ActionTrackerNotification.connection.execute("INSERT INTO action_tracker_notifications(profile_id, action_tracker_id) SELECT DISTINCT c.person_id, #{tracked_action.id} FROM profiles_circles AS p JOIN circles as c ON c.id = p.circle_id WHERE p.profile_id = #{tracked_action.user.id} AND (c.person_id NOT IN (SELECT atn.profile_id FROM action_tracker_notifications AS atn WHERE atn.action_tracker_id = #{tracked_action.id}))")
  28 + end
24 29
25 if tracked_action.user.is_a? Organization 30 if tracked_action.user.is_a? Organization
26 ActionTrackerNotification.connection.execute "insert into action_tracker_notifications(profile_id, action_tracker_id) " + 31 ActionTrackerNotification.connection.execute "insert into action_tracker_notifications(profile_id, action_tracker_id) " +
app/models/approve_article.rb
@@ -9,9 +9,6 @@ class ApproveArticle &lt; Task @@ -9,9 +9,6 @@ class ApproveArticle &lt; Task
9 if target.person? && requestor != target 9 if target.person? && requestor != target
10 self.errors.add(:requestor, _('You can not post articles to other users.')) 10 self.errors.add(:requestor, _('You can not post articles to other users.'))
11 end 11 end
12 - if target.organization? && !target.members.include?(requestor) && target.environment.portal_community != target  
13 - self.errors.add(:requestor, _('Only members can post articles on communities.'))  
14 - end  
15 end 12 end
16 end 13 end
17 14
app/models/article.rb
1 1
2 class Article < ApplicationRecord 2 class Article < ApplicationRecord
3 3
  4 + module Editor
  5 + TEXTILE = 'textile'
  6 + TINY_MCE = 'tiny_mce'
  7 + RAW_HTML = 'raw_html'
  8 + end
  9 +
4 include SanitizeHelper 10 include SanitizeHelper
5 11
6 attr_accessible :name, :body, :abstract, :profile, :tag_list, :parent, 12 attr_accessible :name, :body, :abstract, :profile, :tag_list, :parent,
@@ -11,7 +17,7 @@ class Article &lt; ApplicationRecord @@ -11,7 +17,7 @@ class Article &lt; ApplicationRecord
11 :highlighted, :notify_comments, :display_hits, :slug, 17 :highlighted, :notify_comments, :display_hits, :slug,
12 :external_feed_builder, :display_versions, :external_link, 18 :external_feed_builder, :display_versions, :external_link,
13 :image_builder, :show_to_followers, :archived, 19 :image_builder, :show_to_followers, :archived,
14 - :author, :display_preview, :published_at, :person_followers 20 + :author, :display_preview, :published_at, :person_followers, :editor
15 21
16 extend ActsAsHavingImage::ClassMethods 22 extend ActsAsHavingImage::ClassMethods
17 acts_as_having_image 23 acts_as_having_image
@@ -57,7 +63,7 @@ class Article &lt; ApplicationRecord @@ -57,7 +63,7 @@ class Article &lt; ApplicationRecord
57 _('Content') 63 _('Content')
58 end 64 end
59 65
60 - track_actions :create_article, :after_create, :keep_params => [:name, :url, :lead, :first_image], :if => Proc.new { |a| a.is_trackable? && !a.image? } 66 + track_actions :create_article, :after_create, :keep_params => [:name, :url, :lead, :first_image], :if => Proc.new { |a| a.notifiable? }
61 67
62 # xss_terminate plugin can't sanitize array fields 68 # xss_terminate plugin can't sanitize array fields
63 # sanitize_tag_list is used with SanitizeHelper 69 # sanitize_tag_list is used with SanitizeHelper
@@ -177,10 +183,6 @@ class Article &lt; ApplicationRecord @@ -177,10 +183,6 @@ class Article &lt; ApplicationRecord
177 end 183 end
178 end 184 end
179 185
180 - def is_trackable?  
181 - self.published? && self.notifiable? && self.advertise? && self.profile.public_profile  
182 - end  
183 -  
184 def external_link=(link) 186 def external_link=(link)
185 if !link.blank? && link !~ /^[a-z]+:\/\//i 187 if !link.blank? && link !~ /^[a-z]+:\/\//i
186 link = 'http://' + link 188 link = 'http://' + link
@@ -518,17 +520,12 @@ class Article &lt; ApplicationRecord @@ -518,17 +520,12 @@ class Article &lt; ApplicationRecord
518 ['Folder', 'Blog', 'Forum', 'Gallery'] 520 ['Folder', 'Blog', 'Forum', 'Gallery']
519 end 521 end
520 522
521 - def self.text_article_types  
522 - ['TextArticle', 'TextileArticle', 'TinyMceArticle']  
523 - end  
524 -  
525 scope :published, -> { where 'articles.published = ?', true } 523 scope :published, -> { where 'articles.published = ?', true }
526 scope :folders, -> profile { where 'articles.type IN (?)', profile.folder_types } 524 scope :folders, -> profile { where 'articles.type IN (?)', profile.folder_types }
527 scope :no_folders, -> profile { where 'articles.type NOT IN (?)', profile.folder_types } 525 scope :no_folders, -> profile { where 'articles.type NOT IN (?)', profile.folder_types }
528 scope :galleries, -> { where "articles.type IN ('Gallery')" } 526 scope :galleries, -> { where "articles.type IN ('Gallery')" }
529 scope :images, -> { where :is_image => true } 527 scope :images, -> { where :is_image => true }
530 scope :no_images, -> { where :is_image => false } 528 scope :no_images, -> { where :is_image => false }
531 - scope :text_articles, -> { where 'articles.type IN (?)', text_article_types }  
532 scope :files, -> { where :type => 'UploadedFile' } 529 scope :files, -> { where :type => 'UploadedFile' }
533 scope :with_types, -> types { where 'articles.type IN (?)', types } 530 scope :with_types, -> types { where 'articles.type IN (?)', types }
534 531
@@ -711,10 +708,6 @@ class Article &lt; ApplicationRecord @@ -711,10 +708,6 @@ class Article &lt; ApplicationRecord
711 false 708 false
712 end 709 end
713 710
714 - def tiny_mce?  
715 - false  
716 - end  
717 -  
718 def folder? 711 def folder?
719 false 712 false
720 end 713 end
@@ -848,7 +841,7 @@ class Article &lt; ApplicationRecord @@ -848,7 +841,7 @@ class Article &lt; ApplicationRecord
848 end 841 end
849 842
850 def create_activity 843 def create_activity
851 - if is_trackable? && !image? 844 + if notifiable? && !image?
852 save_action_for_verb 'create_article', [:name, :url, :lead, :first_image], Proc.new{}, :author 845 save_action_for_verb 'create_article', [:name, :url, :lead, :first_image], Proc.new{}, :author
853 end 846 end
854 end 847 end
@@ -879,6 +872,10 @@ class Article &lt; ApplicationRecord @@ -879,6 +872,10 @@ class Article &lt; ApplicationRecord
879 true 872 true
880 end 873 end
881 874
  875 + def editor?(editor)
  876 + self.editor == editor
  877 + end
  878 +
882 private 879 private
883 880
884 def sanitize_tag_list 881 def sanitize_tag_list
app/models/block.rb
@@ -320,6 +320,8 @@ class Block &lt; ApplicationRecord @@ -320,6 +320,8 @@ class Block &lt; ApplicationRecord
320 false 320 false
321 end 321 end
322 322
  323 + attr_accessor :api_content_params
  324 +
323 private 325 private
324 326
325 def home_page_path 327 def home_page_path
app/models/circle.rb
1 class Circle < ApplicationRecord 1 class Circle < ApplicationRecord
  2 + SEARCHABLE_FIELDS = {
  3 + :name => {:label => _('Name'), :weight => 1}
  4 + }
  5 +
  6 + _('Circle')
  7 +
2 has_many :profile_followers 8 has_many :profile_followers
3 belongs_to :person 9 belongs_to :person
4 10
app/models/comment.rb
@@ -212,6 +212,9 @@ class Comment &lt; ApplicationRecord @@ -212,6 +212,9 @@ class Comment &lt; ApplicationRecord
212 user == author || user == profile || user.has_permission?(:moderate_comments, profile) 212 user == author || user == profile || user.has_permission?(:moderate_comments, profile)
213 end 213 end
214 214
  215 + # method used by the API
  216 + alias_method :allow_destroy?, :can_be_destroyed_by?
  217 +
215 def can_be_marked_as_spam_by?(user) 218 def can_be_marked_as_spam_by?(user)
216 return if user.nil? 219 return if user.nil?
217 user == profile || user.has_permission?(:moderate_comments, profile) 220 user == profile || user.has_permission?(:moderate_comments, profile)
app/models/event.rb
@@ -122,10 +122,6 @@ class Event &lt; Article @@ -122,10 +122,6 @@ class Event &lt; Article
122 true 122 true
123 end 123 end
124 124
125 - def tiny_mce?  
126 - true  
127 - end  
128 -  
129 def notifiable? 125 def notifiable?
130 true 126 true
131 end 127 end
app/models/external_feed.rb
@@ -25,7 +25,7 @@ class ExternalFeed &lt; ApplicationRecord @@ -25,7 +25,7 @@ class ExternalFeed &lt; ApplicationRecord
25 end 25 end
26 content = doc.to_s 26 content = doc.to_s
27 27
28 - article = TinyMceArticle.new 28 + article = TextArticle.new
29 article.name = title 29 article.name = title
30 article.profile = blog.profile 30 article.profile = blog.profile
31 article.body = content 31 article.body = content
app/models/favorite_enterprise_person.rb
@@ -2,7 +2,7 @@ class FavoriteEnterprisePerson &lt; ApplicationRecord @@ -2,7 +2,7 @@ class FavoriteEnterprisePerson &lt; ApplicationRecord
2 2
3 attr_accessible :person, :enterprise 3 attr_accessible :person, :enterprise
4 4
5 - track_actions :favorite_enterprise, :after_create, keep_params: [:enterprise_name, :enterprise_url], if: proc{ |f| f.is_trackable? } 5 + track_actions :favorite_enterprise, :after_create, keep_params: [:enterprise_name, :enterprise_url], if: proc{ |f| f.notifiable? }
6 6
7 belongs_to :enterprise 7 belongs_to :enterprise
8 belongs_to :person 8 belongs_to :person
@@ -13,7 +13,7 @@ class FavoriteEnterprisePerson &lt; ApplicationRecord @@ -13,7 +13,7 @@ class FavoriteEnterprisePerson &lt; ApplicationRecord
13 13
14 protected 14 protected
15 15
16 - def is_trackable? 16 + def notifiable?
17 self.enterprise.public? 17 self.enterprise.public?
18 end 18 end
19 19
app/models/gallery.rb
1 class Gallery < Folder 1 class Gallery < Folder
2 2
  3 + settings_items :allow_download, :type => :boolean, :default => false
  4 + attr_accessible :allow_download
  5 +
3 def self.type_name 6 def self.type_name
4 _('Gallery') 7 _('Gallery')
5 end 8 end
app/models/organization.rb
@@ -20,33 +20,28 @@ class Organization &lt; Profile @@ -20,33 +20,28 @@ class Organization &lt; Profile
20 # visible. 20 # visible.
21 # 4) The user is not a member of the organization but the organization is 21 # 4) The user is not a member of the organization but the organization is
22 # visible, public and enabled. 22 # visible, public and enabled.
23 - def self.listed_for_person(person) 23 + scope :listed_for_person, lambda { |person|
  24 +
24 joins('LEFT JOIN "role_assignments" ON ("role_assignments"."resource_id" = "profiles"."id" 25 joins('LEFT JOIN "role_assignments" ON ("role_assignments"."resource_id" = "profiles"."id"
25 AND "role_assignments"."resource_type" = \'Profile\') OR ( 26 AND "role_assignments"."resource_type" = \'Profile\') OR (
26 "role_assignments"."resource_id" = "profiles"."environment_id" AND 27 "role_assignments"."resource_id" = "profiles"."environment_id" AND
27 "role_assignments"."resource_type" = \'Environment\' )') 28 "role_assignments"."resource_type" = \'Environment\' )')
28 .joins('LEFT JOIN "roles" ON "role_assignments"."role_id" = "roles"."id"') 29 .joins('LEFT JOIN "roles" ON "role_assignments"."role_id" = "roles"."id"')
29 .where( 30 .where(
30 - ['( (roles.key = ? OR roles.key = ?) AND role_assignments.accessor_type = ? AND role_assignments.accessor_id = ? )  
31 - OR  
32 - ( ( ( role_assignments.accessor_type = ? AND role_assignments.accessor_id = ? ) OR  
33 - ( profiles.enabled = ? ) ) AND  
34 - ( profiles.visible = ? ) )',  
35 - 'profile_admin', 'environment_administrator', Profile.name, person.id,  
36 - Profile.name, person.id, true, true]  
37 - ).uniq  
38 - end  
39 -  
40 - def self.visible_for_person(person)  
41 - listed_for_person(person).where(  
42 - ['( (roles.key = ? OR roles.key = ?) AND role_assignments.accessor_type = ? AND role_assignments.accessor_id = ? )  
43 - OR 31 + ['( (roles.key = ? OR roles.key = ?) AND role_assignments.accessor_type = ? AND role_assignments.accessor_id = ? ) OR (
  32 + ( ( role_assignments.accessor_type = ? AND role_assignments.accessor_id = ? ) OR ( profiles.enabled = ?)) AND (profiles.visible = ?) )',
  33 + 'profile_admin', 'environment_administrator', Profile.name, person.id, Profile.name, person.id, true, true]
  34 + ).uniq
  35 + }
  36 +
  37 + scope :visible_for_person, lambda { |person|
  38 + listed_for_person(person).where( ['
44 ( ( role_assignments.accessor_type = ? AND role_assignments.accessor_id = ? ) OR 39 ( ( role_assignments.accessor_type = ? AND role_assignments.accessor_id = ? ) OR
45 - ( profiles.enabled = ? AND profiles.public_profile = ? ) )',  
46 - 'profile_admin', 'environment_administrator', Profile.name, person.id, 40 + ( profiles.enabled = ? AND profiles.public_profile = ? ) )',
47 Profile.name, person.id, true, true] 41 Profile.name, person.id, true, true]
48 ) 42 )
49 - end 43 + }
  44 +
50 45
51 settings_items :closed, :type => :boolean, :default => false 46 settings_items :closed, :type => :boolean, :default => false
52 def closed? 47 def closed?
app/models/person.rb
1 # A person is the profile of an user holding all relationships with the rest of the system 1 # A person is the profile of an user holding all relationships with the rest of the system
2 class Person < Profile 2 class Person < Profile
3 3
4 - attr_accessible :organization, :contact_information, :sex, :birth_date, :cell_phone, :comercial_phone, :jabber_id, :personal_website, :nationality, :address_reference, :district, :schooling, :schooling_status, :formation, :custom_formation, :area_of_study, :custom_area_of_study, :professional_activity, :organization_website, :following_articles 4 + attr_accessible :organization, :contact_information, :sex, :birth_date, :cell_phone, :comercial_phone, :jabber_id, :personal_website, :nationality, :address_reference, :district, :schooling, :schooling_status, :formation, :custom_formation, :area_of_study, :custom_area_of_study, :professional_activity, :organization_website, :following_articles, :editor
5 5
6 SEARCH_FILTERS = { 6 SEARCH_FILTERS = {
7 :order => %w[more_recent more_popular more_active], 7 :order => %w[more_recent more_popular more_active],
@@ -124,6 +124,8 @@ class Person &lt; Profile @@ -124,6 +124,8 @@ class Person &lt; Profile
124 where 'profile_suggestions.suggestion_type = ? AND profile_suggestions.enabled = ?', 'Community', true 124 where 'profile_suggestions.suggestion_type = ? AND profile_suggestions.enabled = ?', 'Community', true
125 }, through: :suggested_profiles, source: :suggestion 125 }, through: :suggested_profiles, source: :suggestion
126 126
  127 + has_and_belongs_to_many :marked_scraps, :join_table => :private_scraps, :class_name => 'Scrap'
  128 +
127 scope :more_popular, -> { order 'friends_count DESC' } 129 scope :more_popular, -> { order 'friends_count DESC' }
128 130
129 scope :abusers, -> { 131 scope :abusers, -> {
@@ -344,6 +346,8 @@ class Person &lt; Profile @@ -344,6 +346,8 @@ class Person &lt; Profile
344 346
345 validates_associated :user 347 validates_associated :user
346 348
  349 + validates :editor, inclusion: { in: lambda { |p| p.available_editors } }
  350 +
347 def email 351 def email
348 self.user.nil? ? nil : self.user.email 352 self.user.nil? ? nil : self.user.email
349 end 353 end
@@ -616,8 +620,21 @@ class Person &lt; Profile @@ -616,8 +620,21 @@ class Person &lt; Profile
616 Profile.followed_by self 620 Profile.followed_by self
617 end 621 end
618 622
  623 + def editor?(editor)
  624 + self.editor == editor
  625 + end
  626 +
619 def in_social_circle?(person) 627 def in_social_circle?(person)
620 self.is_a_friend?(person) || super 628 self.is_a_friend?(person) || super
621 end 629 end
622 630
  631 + def available_editors
  632 + available_editors = {
  633 + Article::Editor::TINY_MCE => _('TinyMCE'),
  634 + Article::Editor::TEXTILE => _('Textile')
  635 + }
  636 + available_editors.merge!({Article::Editor::RAW_HTML => _('Raw HTML')}) if self.is_admin?
  637 + available_editors
  638 + end
  639 +
623 end 640 end
app/models/profile.rb
@@ -885,13 +885,14 @@ private :generate_url, :url_options @@ -885,13 +885,14 @@ private :generate_url, :url_options
885 885
886 # returns +true+ if the given +user+ can see profile information about this 886 # returns +true+ if the given +user+ can see profile information about this
887 # +profile+, and +false+ otherwise. 887 # +profile+, and +false+ otherwise.
888 - def display_info_to?(user) 888 + def display_info_to?(user = nil)
889 if self.public? 889 if self.public?
890 true 890 true
891 else 891 else
892 display_private_info_to?(user) 892 display_private_info_to?(user)
893 end 893 end
894 end 894 end
  895 + alias_method :display_to?, :display_info_to?
895 896
896 after_save :update_category_from_region 897 after_save :update_category_from_region
897 def update_category_from_region 898 def update_category_from_region
app/models/raw_html_article.rb
@@ -1,17 +0,0 @@ @@ -1,17 +0,0 @@
1 -class RawHTMLArticle < TextArticle  
2 -  
3 - def self.type_name  
4 - _('HTML')  
5 - end  
6 -  
7 - def self.short_description  
8 - _('Raw HTML text article')  
9 - end  
10 -  
11 - def self.description  
12 - _('Allows HTML without filter (only for admins).')  
13 - end  
14 -  
15 - xss_terminate :only => [ ]  
16 -  
17 -end  
app/models/scrap.rb
@@ -2,7 +2,7 @@ class Scrap &lt; ApplicationRecord @@ -2,7 +2,7 @@ class Scrap &lt; ApplicationRecord
2 2
3 include SanitizeHelper 3 include SanitizeHelper
4 4
5 - attr_accessible :content, :sender_id, :receiver_id, :scrap_id 5 + attr_accessible :content, :sender_id, :receiver_id, :scrap_id, :marked_people
6 6
7 SEARCHABLE_FIELDS = { 7 SEARCHABLE_FIELDS = {
8 :content => {:label => _('Content'), :weight => 1}, 8 :content => {:label => _('Content'), :weight => 1},
@@ -19,6 +19,8 @@ class Scrap &lt; ApplicationRecord @@ -19,6 +19,8 @@ class Scrap &lt; ApplicationRecord
19 where profile_activities: {activity_type: 'Scrap'} 19 where profile_activities: {activity_type: 'Scrap'}
20 }, foreign_key: :activity_id, dependent: :destroy 20 }, foreign_key: :activity_id, dependent: :destroy
21 21
  22 + has_and_belongs_to_many :marked_people, :join_table => :private_scraps, :class_name => 'Person'
  23 +
22 after_create :create_activity 24 after_create :create_activity
23 after_update :update_activity 25 after_update :update_activity
24 26
@@ -65,6 +67,10 @@ class Scrap &lt; ApplicationRecord @@ -65,6 +67,10 @@ class Scrap &lt; ApplicationRecord
65 sender != receiver && (is_root? ? root.receiver.receives_scrap_notification? : receiver.receives_scrap_notification?) 67 sender != receiver && (is_root? ? root.receiver.receives_scrap_notification? : receiver.receives_scrap_notification?)
66 end 68 end
67 69
  70 + def display_to?(user = nil)
  71 + marked_people.blank? || marked_people.include?(user)
  72 + end
  73 +
68 protected 74 protected
69 75
70 def create_activity 76 def create_activity
app/models/suggest_article.rb
@@ -44,7 +44,7 @@ class SuggestArticle &lt; Task @@ -44,7 +44,7 @@ class SuggestArticle &lt; Task
44 type = article[:type].constantize 44 type = article[:type].constantize
45 return type if type < Article 45 return type if type < Article
46 end 46 end
47 - TinyMceArticle 47 + TextArticle
48 end 48 end
49 49
50 def perform 50 def perform
@@ -65,7 +65,7 @@ class SuggestArticle &lt; Task @@ -65,7 +65,7 @@ class SuggestArticle &lt; Task
65 65
66 def information 66 def information
67 variables = requestor.blank? ? {:requestor => sender} : {} 67 variables = requestor.blank? ? {:requestor => sender} : {}
68 - { :message => _('%{requestor} suggested the publication of the article: %{subject}.').html_safe, 68 + { :message => _('%{requestor} suggested the publication %{target_detail} of the article: %{subject}.').html_safe,
69 :variables => variables } 69 :variables => variables }
70 end 70 end
71 71
app/models/text_article.rb
1 # a base class for all text article types. 1 # a base class for all text article types.
2 class TextArticle < Article 2 class TextArticle < Article
3 3
4 - xss_terminate :only => [ :name ], :on => 'validation' 4 + def self.short_description
  5 + _('Text article')
  6 + end
  7 +
  8 + def self.description
  9 + _('Text article to create user content.')
  10 + end
  11 +
  12 + xss_terminate :only => [ :name, :body, :abstract ], :with => 'white_list', :on => 'validation', :if => lambda { |a| !a.editor?(Article::Editor::TEXTILE) && !a.editor?(Article::Editor::RAW_HTML) }
  13 +
  14 + include WhiteListFilter
  15 + filter_iframes :abstract, :body
  16 + def iframe_whitelist
  17 + profile && profile.environment && profile.environment.trusted_sites_for_iframe
  18 + end
5 19
6 def self.type_name 20 def self.type_name
7 _('Article') 21 _('Article')
@@ -21,6 +35,18 @@ class TextArticle &lt; Article @@ -21,6 +35,18 @@ class TextArticle &lt; Article
21 true 35 true
22 end 36 end
23 37
  38 + def can_display_media_panel?
  39 + true
  40 + end
  41 +
  42 + def self.can_display_blocks?
  43 + false
  44 + end
  45 +
  46 + def notifiable?
  47 + true
  48 + end
  49 +
24 before_save :set_relative_path 50 before_save :set_relative_path
25 51
26 def set_relative_path 52 def set_relative_path
@@ -43,4 +69,24 @@ class TextArticle &lt; Article @@ -43,4 +69,24 @@ class TextArticle &lt; Article
43 parent && parent.kind_of?(Blog) && parent.display_preview 69 parent && parent.kind_of?(Blog) && parent.display_preview
44 end 70 end
45 71
  72 + def to_html(options ={})
  73 + content = super(options)
  74 + content = convert_textile_to_html(content) if self.editor?(Article::Editor::TEXTILE)
  75 + content
  76 + end
  77 +
  78 + def lead(length = nil)
  79 + content = super(length)
  80 + content = convert_textile_to_html(content) if self.editor?(Article::Editor::TEXTILE)
  81 + content
  82 + end
  83 +
  84 + protected
  85 +
  86 + def convert_textile_to_html(textile)
  87 + converter = RedCloth.new(textile|| '')
  88 + converter.hard_breaks = false
  89 + sanitize_html(converter.to_html, :white_list)
  90 + end
  91 +
46 end 92 end
app/models/textile_article.rb
@@ -1,44 +0,0 @@ @@ -1,44 +0,0 @@
1 -class TextileArticle < TextArticle  
2 - include SanitizeHelper  
3 -  
4 - def self.short_description  
5 - _('Text article with Textile markup language')  
6 - end  
7 -  
8 - def self.description  
9 - _('Accessible alternative for visually impaired users.')  
10 - end  
11 -  
12 - def to_html(options ={})  
13 - convert_to_html(body)  
14 - end  
15 -  
16 - def lead(length = nil)  
17 - if abstract.blank?  
18 - super  
19 - else  
20 - convert_to_html(abstract)  
21 - end  
22 - end  
23 -  
24 - def notifiable?  
25 - true  
26 - end  
27 -  
28 - def can_display_media_panel?  
29 - true  
30 - end  
31 -  
32 - def self.can_display_blocks?  
33 - false  
34 - end  
35 -  
36 - protected  
37 -  
38 - def convert_to_html(textile)  
39 - converter = RedCloth.new(textile|| '')  
40 - converter.hard_breaks = false  
41 - sanitize_html(converter.to_html, :white_list)  
42 - end  
43 -  
44 -end  
app/models/tiny_mce_article.rb
@@ -1,37 +0,0 @@ @@ -1,37 +0,0 @@
1 -class TinyMceArticle < TextArticle  
2 -  
3 - def self.short_description  
4 - _('Text article with visual editor')  
5 - end  
6 -  
7 - def self.description  
8 - _('Not accessible for visually impaired users.')  
9 - end  
10 -  
11 - xss_terminate :only => [ ]  
12 -  
13 - xss_terminate :only => [ :name, :abstract, :body ], :with => 'white_list', :on => 'validation'  
14 -  
15 - include WhiteListFilter  
16 - filter_iframes :abstract, :body  
17 - def iframe_whitelist  
18 - profile && profile.environment && profile.environment.trusted_sites_for_iframe  
19 - end  
20 -  
21 - def notifiable?  
22 - true  
23 - end  
24 -  
25 - def tiny_mce?  
26 - true  
27 - end  
28 -  
29 - def can_display_media_panel?  
30 - true  
31 - end  
32 -  
33 - def self.can_display_blocks?  
34 - false  
35 - end  
36 -  
37 -end  
app/models/uploaded_file.rb
@@ -9,6 +9,12 @@ class UploadedFile &lt; Article @@ -9,6 +9,12 @@ class UploadedFile &lt; Article
9 9
10 attr_accessible :uploaded_data, :title 10 attr_accessible :uploaded_data, :title
11 11
  12 + include Noosfero::Plugin::HotSpot
  13 +
  14 + def environment
  15 + profile.environment
  16 + end
  17 +
12 def self.type_name 18 def self.type_name
13 _('File') 19 _('File')
14 end 20 end
@@ -184,8 +190,12 @@ class UploadedFile &lt; Article @@ -184,8 +190,12 @@ class UploadedFile &lt; Article
184 true 190 true
185 end 191 end
186 192
  193 + def image?
  194 + mime_type =~ /^image\//
  195 + end
  196 +
187 def notifiable? 197 def notifiable?
188 - true 198 + !image?
189 end 199 end
190 200
191 end 201 end
app/presenters/activity/generic.rb 0 → 100644
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +class ActivityPresenter::Generic < ActivityPresenter
  2 + def self.accepts?(instance)
  3 + 1
  4 + end
  5 +end
app/presenters/activity_presenter.rb 0 → 100644
@@ -0,0 +1,44 @@ @@ -0,0 +1,44 @@
  1 +class ActivityPresenter < Presenter
  2 + def self.base_class
  3 + ActionTracker::Record
  4 + end
  5 +
  6 + def self.available?(instance)
  7 + instance.kind_of?(ActionTracker::Record) || instance.kind_of?(ProfileActivity)
  8 + end
  9 +
  10 + def self.target(instance)
  11 + if instance.kind_of?(ProfileActivity)
  12 + target(instance.activity)
  13 + elsif instance.kind_of?(ActionTracker::Record)
  14 + instance.target
  15 + else
  16 + instance
  17 + end
  18 + end
  19 +
  20 + def self.owner(instance)
  21 + instance.kind_of?(ProfileActivity) ? instance.profile : instance.user
  22 + end
  23 +
  24 + def target
  25 + self.class.target(encapsulated_instance)
  26 + end
  27 +
  28 + def owner
  29 + self.class.owner(encapsulated_instance)
  30 + end
  31 +
  32 + def hidden_for?(user)
  33 + target.respond_to?(:display_to?) && !target.display_to?(user)
  34 + end
  35 +
  36 + def involved?(user)
  37 + owner == user || target == user
  38 + end
  39 +end
  40 +
  41 +# Preload ActivityPresenter subclasses to allow `Presenter.for()` to work
  42 +Dir.glob(File.join('app', 'presenters', 'activity', '*.rb')) do |file|
  43 + load file
  44 +end
app/presenters/file/generic.rb 0 → 100644
@@ -0,0 +1,7 @@ @@ -0,0 +1,7 @@
  1 +# Made to encapsulate any UploadedFile
  2 +class FilePresenter::Generic < FilePresenter
  3 + # if returns low priority, because it is generic.
  4 + def self.accepts?(f)
  5 + 1 if f.is_a? UploadedFile
  6 + end
  7 +end
app/presenters/file/image.rb 0 → 100644
@@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
  1 +class FilePresenter::Image < FilePresenter
  2 + def self.accepts?(f)
  3 + return nil unless f.respond_to? :image?
  4 + f.image? ? 10 : nil
  5 + end
  6 +
  7 + def sized_icon(size)
  8 + public_filename size
  9 + end
  10 +
  11 + def icon_name
  12 + public_filename :icon
  13 + end
  14 +
  15 + def short_description
  16 + _('Image (%s)') % content_type.split('/')[1].upcase
  17 + end
  18 +
  19 + #Overwriting method from FilePresenter to allow download of images
  20 + def download?(view = nil)
  21 + view.blank? || view == 'false'
  22 + end
  23 +end
app/presenters/file_presenter.rb 0 → 100644
@@ -0,0 +1,80 @@ @@ -0,0 +1,80 @@
  1 +class FilePresenter < Presenter
  2 + def self.base_class
  3 + Article
  4 + end
  5 +
  6 + def self.available?(instance)
  7 + instance.kind_of?(UploadedFile) && !instance.kind_of?(Image)
  8 + end
  9 +
  10 + def download? view = nil
  11 + view.blank?
  12 + end
  13 +
  14 + def short_description
  15 + file_type = if content_type.present?
  16 + content_type.sub(/^application\//, '').sub(/^x-/, '').sub(/^image\//, '')
  17 + else
  18 + _('Unknown')
  19 + end
  20 + _("File (%s)") % file_type
  21 + end
  22 +
  23 + # Define the css classes to style the page fragment with the file related
  24 + # content. If you want other classes to identify this area to your
  25 + # customized presenter, so do this:
  26 + # def css_class_list
  27 + # [super, 'myclass'].flatten
  28 + # end
  29 + def css_class_list
  30 + [ encapsulated_instance.css_class_list,
  31 + 'file-' + self.class.to_s.split(/:+/).map(&:underscore)[1..-1].join('-'),
  32 + 'content-type_' + self.content_type.split('/')[0],
  33 + 'content-type_' + self.content_type.gsub(/[^a-z0-9]/i,'-')
  34 + ].flatten
  35 + end
  36 +
  37 + # Enable file presenter to customize the css classes on view_page.rhtml
  38 + # You may not overwrite this method on your customized presenter.
  39 + def css_class_name
  40 + [css_class_list].flatten.compact.join(' ')
  41 + end
  42 +
  43 + # The generic icon class-name or the specific file path.
  44 + # You may replace this method on your custom FilePresenter.
  45 + # See the current used icons class-names in public/designs/icons/tango/style.css
  46 + def icon_name
  47 + if mime_type
  48 + [ mime_type.split('/')[0], mime_type.gsub(/[^a-z0-9]/i, '-') ]
  49 + else
  50 + 'upload-file'
  51 + end
  52 + end
  53 +
  54 + # Automatic render `file_presenter/<custom>.html.erb` to display your
  55 + # custom presenter html content.
  56 + # You may not overwrite this method on your customized presenter.
  57 + # A variable with the same presenter name will be created to refer
  58 + # to the file object.
  59 + # Example:
  60 + # The `FilePresenter::Image` render `file_presenter/image.html.erb`
  61 + # inside the `file_presenter/image.html.erb` you can access the
  62 + # required `FilePresenter::Image` instance in the `image` variable.
  63 + def to_html(options = {})
  64 + file = self
  65 + proc do
  66 + render :partial => file.class.to_s.underscore,
  67 + :locals => { :options => options },
  68 + :object => file
  69 + end
  70 + end
  71 +end
  72 +
  73 +Dir.glob(File.join('app', 'presenters', 'file', '*.rb')) do |file|
  74 + load file
  75 +end
  76 +
  77 +# Preload FilePresenters from plugins to allow `FilePresenter.for()` to work
  78 +Dir.glob(File.join('plugins', '*', 'lib', 'presenters', '*.rb')) do |file|
  79 + load file
  80 +end
app/presenters/generic.rb
@@ -1,7 +0,0 @@ @@ -1,7 +0,0 @@
1 -# Made to encapsulate any UploadedFile  
2 -class FilePresenter::Generic < FilePresenter  
3 - # if returns low priority, because it is generic.  
4 - def self.accepts?(f)  
5 - 1 if f.is_a? UploadedFile  
6 - end  
7 -end  
app/presenters/image.rb
@@ -1,23 +0,0 @@ @@ -1,23 +0,0 @@
1 -class FilePresenter::Image < FilePresenter  
2 - def self.accepts?(f)  
3 - return nil unless f.respond_to? :image?  
4 - f.image? ? 10 : nil  
5 - end  
6 -  
7 - def sized_icon(size)  
8 - public_filename size  
9 - end  
10 -  
11 - def icon_name  
12 - public_filename :icon  
13 - end  
14 -  
15 - def short_description  
16 - _('Image (%s)') % content_type.split('/')[1].upcase  
17 - end  
18 -  
19 - #Overwriting method from FilePresenter to allow download of images  
20 - def download?(view = nil)  
21 - view.blank? || view == 'false'  
22 - end  
23 -end  
app/views/account/_signup_form.html.erb
@@ -111,7 +111,7 @@ @@ -111,7 +111,7 @@
111 111
112 <% unless @terms_of_use.blank? %> 112 <% unless @terms_of_use.blank? %>
113 <div id='terms-of-use-box' class='formfieldline'> 113 <div id='terms-of-use-box' class='formfieldline'>
114 - <%= labelled_check_box(_('I accept the %s') % link_to(_('terms of use'), {:controller => 'home', :action => 'terms'}, :target => '_blank'), 'user[terms_accepted]') %> 114 + <%= labelled_check_box(_('I accept the %s').html_safe % link_to(_('terms of use'), {:controller => 'home', :action => 'terms'}, :target => '_blank'), 'user[terms_accepted]') %>
115 </div> 115 </div>
116 <% end %> 116 <% end %>
117 117
app/views/admin_panel/_signup_intro.html.erb
@@ -2,4 +2,4 @@ @@ -2,4 +2,4 @@
2 <%= _('This text will be shown to the user on the top of the sign up form.') %> 2 <%= _('This text will be shown to the user on the top of the sign up form.') %>
3 </div> 3 </div>
4 4
5 -<%= labelled_form_field(_('Body'), text_area(:environment, :signup_intro, :cols => 40, :style => 'width: 100%', :class => 'mceEditor')) %> 5 +<%= labelled_form_field(_('Body'), text_area(:environment, :signup_intro, :cols => 40, :style => 'width: 100%', :class => current_editor)) %>
app/views/admin_panel/_signup_welcome_screen.html.erb
1 <div class='description'> 1 <div class='description'>
2 <%= _('If you enable this feature on the "Features" section of the Administration Panel, this text will be shown as a welcome message to users after signup.') %> 2 <%= _('If you enable this feature on the "Features" section of the Administration Panel, this text will be shown as a welcome message to users after signup.') %>
3 </div> 3 </div>
4 -<%= labelled_form_field(_('Body'), text_area(:environment, :signup_welcome_screen_body, :cols => 40, :style => 'width: 100%', :class => 'mceEditor')) %> 4 +<%= labelled_form_field(_('Body'), text_area(:environment, :signup_welcome_screen_body, :cols => 40, :style => 'width: 100%', :class => current_editor)) %>
5 5
6 <div class='description'> 6 <div class='description'>
7 <%= _('If this content is left blank, the following page will be displayed to the user:') %> 7 <%= _('If this content is left blank, the following page will be displayed to the user:') %>
app/views/admin_panel/_signup_welcome_text.html.erb
@@ -4,4 +4,4 @@ @@ -4,4 +4,4 @@
4 </div> 4 </div>
5 5
6 <%= labelled_form_field(_('Subject'), text_field(:environment, :signup_welcome_text_subject, :style => 'width:100%')) %> 6 <%= labelled_form_field(_('Subject'), text_field(:environment, :signup_welcome_text_subject, :style => 'width:100%')) %>
7 -<%= labelled_form_field(_('Body'), text_area(:environment, :signup_welcome_text_body, :cols => 40, :style => 'width: 100%', :class => 'mceEditor')) %> 7 +<%= labelled_form_field(_('Body'), text_area(:environment, :signup_welcome_text_body, :cols => 40, :style => 'width: 100%', :class => current_editor)) %>
app/views/admin_panel/_site_info.html.erb
@@ -31,4 +31,4 @@ @@ -31,4 +31,4 @@
31 <%= balanced_table(fields)%> 31 <%= balanced_table(fields)%>
32 32
33 <br /> 33 <br />
34 -<%= labelled_form_field _('Homepage content'), text_area(:environment, :description, :cols => 40, :style => 'width: 90%', :class => 'mceEditor') %> 34 +<%= labelled_form_field _('Homepage content'), text_area(:environment, :description, :cols => 40, :style => 'width: 90%', :class => current_editor) %>
app/views/admin_panel/_terms_of_use.html.erb
1 -<%= f.text_area :terms_of_use, :cols => 40, :style => 'width: 90%', :class => 'mceEditor' %> 1 +<%= f.text_area :terms_of_use, :cols => 40, :style => 'width: 90%', :class => current_editor %>
app/views/admin_panel/message_for_disabled_enterprise.html.erb
1 <h2><%= _('Site info') %></h2> 1 <h2><%= _('Site info') %></h2>
2 2
3 -<%= render :file => 'shared/tiny_mce' %>  
4 -  
5 <%= labelled_form_for :environment, :url => {:action => 'site_info'} do |f| %> 3 <%= labelled_form_for :environment, :url => {:action => 'site_info'} do |f| %>
6 4
7 - <%= f.text_area :message_for_disabled_enterprise, :cols => 40, :style => 'width: 90%' %> 5 + <%= f.text_area :message_for_disabled_enterprise, :cols => 40, :style => 'width: 90%', :class => current_editor %>
8 6
9 <%= button_bar do %> 7 <%= button_bar do %>
10 <%= submit_button(:save, _('Save')) %> 8 <%= submit_button(:save, _('Save')) %>
app/views/admin_panel/site_info.html.erb
@@ -2,8 +2,6 @@ @@ -2,8 +2,6 @@
2 2
3 <%= error_messages_for :environment %> 3 <%= error_messages_for :environment %>
4 4
5 -<%= render :file => 'shared/tiny_mce' %>  
6 -  
7 <%= labelled_form_for :environment do |f| %> 5 <%= labelled_form_for :environment do |f| %>
8 <% tabs = [] %> 6 <% tabs = [] %>
9 <% tabs << {:title => _('Site info'), :id => 'site-info', 7 <% tabs << {:title => _('Site info'), :id => 'site-info',
app/views/api/index.html.erb
1 <h1>EndPoints</h1> 1 <h1>EndPoints</h1>
2 2
3 <div style="float: right"> 3 <div style="float: right">
4 - <%= s_('api-playground|Try the %s') % link_to('API Playground', {:controller => 'api', :action => 'playground'}) %> 4 + <%= s_('api-playground|Try the %s').html_safe % link_to('API Playground', {:controller => 'api', :action => 'playground'}) %>
5 </div> 5 </div>
6 6
7 <%= endpoints.map do |endpoint| 7 <%= endpoints.map do |endpoint|
8 app = endpoint.options[:app].to_s 8 app = endpoint.options[:app].to_s
9 unless app.blank? 9 unless app.blank?
10 - content_tag(:h2, app.split('::').last.to_s, title: app) + 10 + content_tag(:h2, app.split('::').last.to_s, title: app).html_safe +
11 (content_tag :ul do 11 (content_tag :ul do
12 endpoint.routes.map do |route| 12 endpoint.routes.map do |route|
13 content_tag :li do 13 content_tag :li do
14 content_tag(:strong, route.route_method) + ' ' + 14 content_tag(:strong, route.route_method) + ' ' +
15 - route.route_path.gsub(':version', content_tag(:b, route.route_version)) 15 + route.route_path.gsub(':version', content_tag(:b, route.route_version)).html_safe
16 end 16 end
17 - end.join "\n" 17 + end.safe_join "\n"
18 end) 18 end)
19 end 19 end
20 -end.join "\n" %> 20 +end.safe_join "\n" %>
app/views/categories/_form.html.erb
1 -<%= stylesheet_link_tag 'spectrum.css' %>  
2 -<%= javascript_include_tag "spectrum.js" %> 1 +<%= stylesheet_link_tag 'vendor/spectrum.css' %>
  2 +<%= javascript_include_tag "vendor/spectrum.js" %>
3 <%= javascript_include_tag "colorpicker-noosfero.js" %> 3 <%= javascript_include_tag "colorpicker-noosfero.js" %>
4 4
5 <%= error_messages_for 'category' %> 5 <%= error_messages_for 'category' %>
app/views/cms/_article.html.erb
1 -_tiny_mce_article.html.erb  
2 \ No newline at end of file 1 \ No newline at end of file
  2 +_text_article.html.erb
3 \ No newline at end of file 3 \ No newline at end of file
app/views/cms/_blog.html.erb
@@ -2,8 +2,6 @@ @@ -2,8 +2,6 @@
2 2
3 <h1><%= _('My Blog') %></h1> 3 <h1><%= _('My Blog') %></h1>
4 4
5 -<%= render :file => 'shared/tiny_mce' %>  
6 -  
7 <%= required f.text_field(:name, :size => '64', :maxlength => 150, :onchange => "updateUrlField(this, 'article_slug')") %> 5 <%= required f.text_field(:name, :size => '64', :maxlength => 150, :onchange => "updateUrlField(this, 'article_slug')") %>
8 6
9 <%= render :partial => 'general_fields' %> 7 <%= render :partial => 'general_fields' %>
@@ -53,7 +51,7 @@ @@ -53,7 +51,7 @@
53 %> 51 %>
54 </div> 52 </div>
55 53
56 -<%= labelled_form_field(_('Description:'), text_area(:article, :body, :rows => 10, :class => 'mceEditor')) %> 54 +<%= labelled_form_field(_('Description:'), text_area(:article, :body, :rows => 10, :class => current_editor)) %>
57 55
58 <div id="blog-image-builder"> 56 <div id="blog-image-builder">
59 <%= f.fields_for :image_builder, @article.image do |i| %> 57 <%= f.fields_for :image_builder, @article.image do |i| %>
app/views/cms/_enterprise_homepage.html.erb
1 -<%= render :file => 'shared/tiny_mce' %>  
2 -  
3 -<%= labelled_form_field(_('Text'), text_area(:article, 'body', :cols => 40, :style => 'width:99%', :class => 'mceEditor')) %> 1 +<%= labelled_form_field(_('Text'), text_area(:article, 'body', :cols => 40, :style => 'width:99%', :class => current_editor)) %>
4 2
app/views/cms/_event.html.erb
1 <%= required_fields_message %> 1 <%= required_fields_message %>
2 2
3 -<%# TODO add Textile help here %>  
4 -<%= render :file => 'shared/tiny_mce' %>  
5 -  
6 <%= required f.text_field('name', :size => '64', :maxlength => 150) %> 3 <%= required f.text_field('name', :size => '64', :maxlength => 150) %>
7 4
8 <%= render :partial => 'general_fields' %> 5 <%= render :partial => 'general_fields' %>
@@ -16,4 +13,4 @@ @@ -16,4 +13,4 @@
16 13
17 <%= labelled_form_field(_('Address:'), text_field(:article, :address)) %> 14 <%= labelled_form_field(_('Address:'), text_field(:article, :address)) %>
18 15
19 -<%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true, :body_label => 'Information about the event:'} %> 16 +<%= render :partial => 'shared/lead_and_body', :locals => {:body_label => 'Information about the event:'} %>
app/views/cms/_forum.html.erb
@@ -4,18 +4,16 @@ @@ -4,18 +4,16 @@
4 4
5 <%= required_fields_message %> 5 <%= required_fields_message %>
6 6
7 -<%= render :file => 'shared/tiny_mce' %>  
8 -  
9 <%= required f.text_field(:name, :size => '64', :maxlength => 150, :onchange => "updateUrlField(this, 'article_slug')") %> 7 <%= required f.text_field(:name, :size => '64', :maxlength => 150, :onchange => "updateUrlField(this, 'article_slug')") %>
10 8
11 <%= render :partial => 'general_fields' %> 9 <%= render :partial => 'general_fields' %>
12 10
13 -<%= labelled_form_field(_('Description:'), text_area(:article, :body, :class => 'mceEditor', :cols => 64, :rows => 10)) %> 11 +<%= labelled_form_field(_('Description:'), text_area(:article, :body, :class => current_editor, :cols => 64, :rows => 10)) %>
14 12
15 <%= labelled_form_field(_('Posts per page:'), f.select(:posts_per_page, Forum.posts_per_page_options)) %> 13 <%= labelled_form_field(_('Posts per page:'), f.select(:posts_per_page, Forum.posts_per_page_options)) %>
16 14
17 <%= labelled_form_field(_('Has terms of use:'), check_box(:article, :has_terms_of_use))%> 15 <%= labelled_form_field(_('Has terms of use:'), check_box(:article, :has_terms_of_use))%>
18 16
19 <div id="text_area_terms_of_use"> 17 <div id="text_area_terms_of_use">
20 - <%= labelled_form_field(_('Terms of use:'), text_area(:article, :terms_of_use, :class => 'mceEditor',:cols => 64, :rows => 10)) %> 18 + <%= labelled_form_field(_('Terms of use:'), text_area(:article, :terms_of_use, :class => current_editor,:cols => 64, :rows => 10)) %>
21 </div> 19 </div>
app/views/cms/_raw_html_article.html.erb
@@ -1,8 +0,0 @@ @@ -1,8 +0,0 @@
1 -<%= required_fields_message %>  
2 -  
3 -<%= required labelled_form_field(_('Title'), text_field(:article, 'name', :size => '64', :maxlength => 150)) %>  
4 -  
5 -<%= render :partial => 'text_fields' %>  
6 -<%= render :partial => 'general_fields' %>  
7 -<%= render :partial => 'translatable' %>  
8 -<%= render :partial => 'shared/lead_and_body' %>  
app/views/cms/_text_article.html.erb 0 → 100644
@@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
  1 +<%= required_fields_message %>
  2 +
  3 +<%= required labelled_form_field(_('Title'), text_field(:article, 'name', :size => '72', :maxlength => 150)) %>
  4 +
  5 +<%= render :partial => 'text_fields' %>
  6 +<%= render :partial => 'general_fields' %>
  7 +<%= render :partial => 'translatable' %>
  8 +
  9 +<%= render :partial => 'shared/lead_and_body' %>
  10 +
app/views/cms/_text_editor_sidebar.html.erb
@@ -7,7 +7,7 @@ @@ -7,7 +7,7 @@
7 7
8 <div class='header'><strong><%= _('Insert media') %></strong><%= button('vertical-toggle', _('Show/Hide'), '#') %></div> 8 <div class='header'><strong><%= _('Insert media') %></strong><%= button('vertical-toggle', _('Show/Hide'), '#') %></div>
9 9
10 - <%= render(:partial => 'textile_quick_reference') if @article.is_a?(TextileArticle) %> 10 + <%= render(:partial => 'textile_quick_reference') if @article.editor?(Article::Editor::TEXTILE) %>
11 <div class='text-editor-sidebar-box' id='media-upload-box'> 11 <div class='text-editor-sidebar-box' id='media-upload-box'>
12 <div id='media-upload-form'> 12 <div id='media-upload-form'>
13 <%= form_tag({ :action => 'media_upload' }, :multipart => true) do %> 13 <%= form_tag({ :action => 'media_upload' }, :multipart => true) do %>
@@ -48,4 +48,4 @@ @@ -48,4 +48,4 @@
48 </script> 48 </script>
49 49
50 <%= render :partial => 'media_new_folder', :locals => {:default_folder => default_folder} %> 50 <%= render :partial => 'media_new_folder', :locals => {:default_folder => default_folder} %>
51 -<%= javascript_include_tag 'jquery.fileupload.js', 'tmpl.js', 'media-panel.js' %> 51 +<%= javascript_include_tag 'vendor/jquery.fileupload.js', 'vendor/tmpl.js', 'media-panel.js' %>
app/views/cms/_textile_article.html.erb
@@ -1,10 +0,0 @@ @@ -1,10 +0,0 @@
1 -<%= required_fields_message %>  
2 -  
3 -<%# TODO add Textile help here %>  
4 -  
5 -<%= required labelled_form_field(_('Title'), text_field(:article, 'name', :size => '72', :maxlength => 150)) %>  
6 -  
7 -<%= render :partial => 'text_fields' %>  
8 -<%= render :partial => 'general_fields' %>  
9 -<%= render :partial => 'translatable' %>  
10 -<%= render :partial => 'shared/lead_and_body' %>  
app/views/cms/_tiny_mce_article.html.erb
@@ -1,12 +0,0 @@ @@ -1,12 +0,0 @@
1 -<%= required_fields_message %>  
2 -  
3 -<%= render :file => 'shared/tiny_mce' %>  
4 -  
5 -<div>  
6 - <%= required labelled_form_field(_('Title'), text_field(:article, 'name', :size => '64', :maxlength => 150)) %>  
7 -  
8 - <%= render :partial => 'text_fields' %>  
9 - <%= render :partial => 'general_fields' %>  
10 - <%= render :partial => 'translatable' %>  
11 - <%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true} %>  
12 -</div>  
app/views/cms/edit.html.erb
@@ -34,7 +34,7 @@ @@ -34,7 +34,7 @@
34 34
35 <br /> 35 <br />
36 36
37 - <%= f.text_field('tag_list', :size => 64) %> 37 + <%= f.text_field 'tag_list', size: 64, value: @article.tag_list.join(',') %>
38 <%= content_tag( 'small', _('Separate tags with commas') ) %> 38 <%= content_tag( 'small', _('Separate tags with commas') ) %>
39 39
40 <script> 40 <script>
app/views/cms/suggest_an_article.html.erb
@@ -2,8 +2,6 @@ @@ -2,8 +2,6 @@
2 2
3 <%= required_fields_message %> 3 <%= required_fields_message %>
4 4
5 -<%= render :file => 'shared/tiny_mce' %>  
6 -  
7 <%= labelled_form_for 'task' do |f| %> 5 <%= labelled_form_for 'task' do |f| %>
8 6
9 <%= required labelled_form_field(_('Title'), text_field('task[article]', 'name', :size => 50)) %> 7 <%= required labelled_form_field(_('Title'), text_field('task[article]', 'name', :size => 50)) %>
@@ -17,7 +15,7 @@ @@ -17,7 +15,7 @@
17 <%= required labelled_form_field(_('Email'), text_field(:task, 'email')) %> 15 <%= required labelled_form_field(_('Email'), text_field(:task, 'email')) %>
18 <% end %> 16 <% end %>
19 17
20 - <%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true, :object => 'task[article]'} %> 18 + <%= render :partial => 'shared/lead_and_body', :locals => {:object => 'task[article]'} %>
21 19
22 <%= hidden_field_tag('back_to', @back_to) %> 20 <%= hidden_field_tag('back_to', @back_to) %>
23 21
app/views/contact/new.html.erb
@@ -25,8 +25,7 @@ @@ -25,8 +25,7 @@
25 25
26 <%= required f.text_field(:subject) %> 26 <%= required f.text_field(:subject) %>
27 27
28 - <%= render :file => 'shared/tiny_mce' %>  
29 - <%= required f.text_area(:message, :class => 'mceEditor') %> 28 + <%= required f.text_area(:message, :class => current_editor) %>
30 29
31 <%= labelled_form_field check_box(:contact, :receive_a_copy) + _('I want to receive a copy of the message in my e-mail.'), '' %> 30 <%= labelled_form_field check_box(:contact, :receive_a_copy) + _('I want to receive a copy of the message in my e-mail.'), '' %>
32 31
app/views/email_templates/_form.html.erb
@@ -19,8 +19,7 @@ @@ -19,8 +19,7 @@
19 <%= @template_params_allowed %> 19 <%= @template_params_allowed %>
20 </div> 20 </div>
21 </div> 21 </div>
22 - <%= render :file => 'shared/tiny_mce' %>  
23 - <%= labelled_form_field(_('Body:'), f.text_area(:body, :class => 'mceEditor')) %> 22 + <%= labelled_form_field(_('Body:'), f.text_area(:body, :class => current_editor)) %>
24 </div> 23 </div>
25 24
26 <div class="actions"> 25 <div class="actions">
app/views/file_presenter/_image.html.erb
1 <% if image.gallery? && options[:gallery_view] %> 1 <% if image.gallery? && options[:gallery_view] %>
2 <% 2 <%
3 images = image.parent.images 3 images = image.parent.images
4 - current_index = images.index(image.encapsulated_file) 4 + current_index = images.index(image.encapsulated_instance)
5 total_of_images = images.count 5 total_of_images = images.count
6 link_to_previous = if current_index >= 1 6 link_to_previous = if current_index >= 1
7 link_to(_('&laquo; Previous').html_safe, images[current_index - 1].view_url, :class => 'previous') 7 link_to(_('&laquo; Previous').html_safe, images[current_index - 1].view_url, :class => 'previous')
@@ -30,7 +30,10 @@ @@ -30,7 +30,10 @@
30 30
31 <img src="<%= [Noosfero.root, image.public_filename(:display)].join %>" class="<%=image.css_class_name%>"> 31 <img src="<%= [Noosfero.root, image.public_filename(:display)].join %>" class="<%=image.css_class_name%>">
32 32
  33 +<% if image.parent.is_a?(Gallery) && image.parent.allow_download %>
  34 + <%= link_to _('Download image'), [Noosfero.root, image.public_filename(:display)].join, download: image.filename, id: 'download-image-id', class: "button with-text icon-save" %>
  35 +<% end %>
  36 +
33 <div class="uploaded-file-description <%= 'empty' if image.abstract.blank? %>"> 37 <div class="uploaded-file-description <%= 'empty' if image.abstract.blank? %>">
34 <%= image.abstract %> 38 <%= image.abstract %>
35 </div> 39 </div>
36 -  
app/views/home/terms.html.erb
1 <h1><%= _('Terms of use - %s') % environment.name %></h1> 1 <h1><%= _('Terms of use - %s') % environment.name %></h1>
2 -<%= environment.terms_of_use %> 2 +<%= environment.terms_of_use.html_safe %>
app/views/layouts/application-ng.html.erb
@@ -35,6 +35,9 @@ @@ -35,6 +35,9 @@
35 noosfero.profile = <%= (@profile.identifier if @profile).to_json.html_safe %> 35 noosfero.profile = <%= (@profile.identifier if @profile).to_json.html_safe %>
36 </script> 36 </script>
37 37
  38 + <% if current_editor_is?(Article::Editor::TINY_MCE) %>
  39 + <%= render :file => 'shared/tiny_mce' %>
  40 + <% end %>
38 </head> 41 </head>
39 <body class="<%= h body_classes %>"> 42 <body class="<%= h body_classes %>">
40 <a href="#content" id="link-go-content"><span><%= _("Go to the content") %></span></a> 43 <a href="#content" id="link-go-content"><span><%= _("Go to the content") %></span></a>
@@ -72,7 +75,7 @@ @@ -72,7 +75,7 @@
72 </div><!-- end id="content" --> 75 </div><!-- end id="content" -->
73 </div><!-- end id="wrap-2" --> 76 </div><!-- end id="wrap-2" -->
74 </div><!-- end id="wrap-1" --> 77 </div><!-- end id="wrap-1" -->
75 - <%= render_environment_features(:logged_in) if logged_in? %> 78 + <%= render_environment_features(:logged_in).html_safe if logged_in? %>
76 <div id="footer"> 79 <div id="footer">
77 <div id="theme-footer"> 80 <div id="theme-footer">
78 <%= theme_footer %> 81 <%= theme_footer %>
@@ -86,9 +89,9 @@ @@ -86,9 +89,9 @@
86 <%= 89 <%=
87 str = (@plugins.dispatch(:body_ending).map do |content| 90 str = (@plugins.dispatch(:body_ending).map do |content|
88 if content.respond_to?(:call) then 91 if content.respond_to?(:call) then
89 - instance_exec(&content) 92 + instance_exec(&content).html_safe
90 else 93 else
91 - content 94 + content.html_safe
92 end 95 end
93 end) 96 end)
94 safe_join(str, "\n") 97 safe_join(str, "\n")
app/views/layouts/slideshow.html.erb
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 %></title> 11 %></title>
12 12
13 <%= stylesheet_import "slideshow" %> 13 <%= stylesheet_import "slideshow" %>
14 - <%= javascript_include_tag 'jquery-2.1.1.min', 'sliderjs', 'pikachoose' %> 14 + <%= javascript_include_tag 'jquery-2.1.1.min', 'vendor/sliderjs', 'vendor/pikachoose' %>
15 <script type="text/javascript"> 15 <script type="text/javascript">
16 $(document).ready(function (){ 16 $(document).ready(function (){
17 $("#slideshow").PikaChoose({ 17 $("#slideshow").PikaChoose({
app/views/profile/_default_activity.html.erb
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 <%= link_to(profile_image(activity.user, :minor), activity.user.url) %> 2 <%= link_to(profile_image(activity.user, :minor), activity.user.url) %>
3 </div> 3 </div>
4 <div class='profile-activity-description'> 4 <div class='profile-activity-description'>
5 - <p class='profile-activity-text'><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></p> 5 + <p class='profile-activity-text'><%= link_to activity.user.name, activity.user.url %> <%= describe(activity).html_safe %></p>
6 <p class='profile-activity-time'><%= time_ago_in_words(activity.created_at) %></p> 6 <p class='profile-activity-time'><%= time_ago_in_words(activity.created_at) %></p>
7 <div class='profile-wall-actions'> 7 <div class='profile-wall-actions'>
8 <%= link_to s_('profile|Comment'), '#', { :class => 'focus-on-comment'} %> 8 <%= link_to s_('profile|Comment'), '#', { :class => 'focus-on-comment'} %>
app/views/profile/_favorite_enterprise.html.erb
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 </div> 3 </div>
4 <div class='profile-activity-description'> 4 <div class='profile-activity-description'>
5 <p class='profile-activity-text'> 5 <p class='profile-activity-text'>
6 - <%= link_to activity.user.short_name(nil), activity.user.url %> <%= describe activity %> 6 + <%= link_to activity.user.short_name(nil), activity.user.url %> <%= describe(activity).html_safe %>
7 </p> 7 </p>
8 <p class='profile-activity-time'><%= time_ago_in_words activity.created_at %></p> 8 <p class='profile-activity-time'><%= time_ago_in_words activity.created_at %></p>
9 9
app/views/profile/_leave_scrap.html.erb
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 <%= link_to(profile_image(activity.user, :minor), activity.user.url) %> 2 <%= link_to(profile_image(activity.user, :minor), activity.user.url) %>
3 </div> 3 </div>
4 <div class='profile-activity-description'> 4 <div class='profile-activity-description'>
5 - <p class='profile-activity-text'><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></p> 5 + <p class='profile-activity-text'><%= link_to activity.user.name, activity.user.url %> <%= describe(activity).html_safe %></p>
6 <p class='profile-activity-time'><%= time_ago_in_words(activity.created_at) %></p> 6 <p class='profile-activity-time'><%= time_ago_in_words(activity.created_at) %></p>
7 <div class='profile-wall-actions'> 7 <div class='profile-wall-actions'>
8 <%= link_to_function(_('Remove'), 'remove_item_wall(this, \'%s\', \'%s\', \'%s\'); return false ;' % [".profile-activity-item", url_for(:profile => params[:profile], :action => :remove_activity, :activity_id => activity.id, :view => params[:view]), _('Are you sure you want to remove this activity and all its replies?')]) if logged_in? && current_person == @profile %> 8 <%= link_to_function(_('Remove'), 'remove_item_wall(this, \'%s\', \'%s\', \'%s\'); return false ;' % [".profile-activity-item", url_for(:profile => params[:profile], :action => :remove_activity, :activity_id => activity.id, :view => params[:view]), _('Are you sure you want to remove this activity and all its replies?')]) if logged_in? && current_person == @profile %>
app/views/profile/_profile_activities_list.html.erb
@@ -12,6 +12,6 @@ @@ -12,6 +12,6 @@
12 12
13 <% if activities.current_page < activities.total_pages %> 13 <% if activities.current_page < activities.total_pages %>
14 <div id='profile_activities_page_<%= activities.current_page %>'> 14 <div id='profile_activities_page_<%= activities.current_page %>'>
15 - <%= button_to_remote :add, _('View more'), :url => {:action => 'view_more_activities', :page => (activities.current_page + 1)}, :update => "profile_activities_page_#{activities.current_page}" %> 15 + <%= button_to_remote :add, _('View more'), :url => {:action => 'view_more_activities', :page => (activities.current_page + 1), :offsets => @offsets, :kind => 'wall'}, :update => "profile_activities_page_#{activities.current_page}" %>
16 </div> 16 </div>
17 <% end %> 17 <% end %>
app/views/profile/_profile_network.html.erb
1 <h3><%= _("%s's network activity") % @profile.name %></h3> 1 <h3><%= _("%s's network activity") % @profile.name %></h3>
2 <ul id='network-activities' class='profile-activities'> 2 <ul id='network-activities' class='profile-activities'>
3 - <%= render :partial => 'profile_network_activities', :locals => {:network_activities => @network_activities} %> 3 + <%= render :partial => 'profile_network_activities', :locals => {:activities => @network_activities} %>
4 </ul> 4 </ul>
app/views/profile/_profile_network_activities.html.erb
1 -<% network_activities.each do |activity| %> 1 +<% activities.each do |activity| %>
2 <%= render :partial => 'profile_activity', :locals => { :activity => activity, :tab_action => 'network' } if activity.visible? %> 2 <%= render :partial => 'profile_activity', :locals => { :activity => activity, :tab_action => 'network' } if activity.visible? %>
3 <% end %> 3 <% end %>
4 -<% if network_activities.current_page < network_activities.total_pages %>  
5 - <div id='profile_network_activities_page_<%= network_activities.current_page %>'>  
6 - <%= button_to_remote :add, _('View more'), :url => {:action => 'view_more_network_activities', :page => (network_activities.current_page + 1)}, :update => "profile_network_activities_page_#{network_activities.current_page}" %> 4 +<% if activities.current_page < activities.total_pages %>
  5 + <div id='profile_network_activities_page_<%= activities.current_page %>'>
  6 + <%= button_to_remote :add, _('View more'), :url => {:action => 'view_more_activities', :page => (activities.current_page + 1), :offsets => @offsets, :kind => 'network'}, :update => "profile_network_activities_page_#{activities.current_page}" %>
7 </div> 7 </div>
8 <% end %> 8 <% end %>
app/views/profile/_profile_wall.html.erb
1 <h3><%= _("%s's wall") % @profile.name %></h3> 1 <h3><%= _("%s's wall") % @profile.name %></h3>
2 <div id='leave_scrap'> 2 <div id='leave_scrap'>
3 <%= flash[:error] %> 3 <%= flash[:error] %>
4 - <%= form_remote_tag :url => {:controller => 'profile', :action => 'leave_scrap', :tab_action => 'wall' }, :update => 'profile_activities', :success => "jQuery('#leave_scrap_content').val('')", :complete => "jQuery('#leave_scrap_form').removeClass('loading').find('*').attr('disabled', false)", :loading => "jQuery('#leave_scrap_form').addClass('loading').find('*').attr('disabled', true)", :html => {:id => 'leave_scrap_form' } do %>  
5 - <%= limited_text_area :scrap, :content, 420, 'leave_scrap_content', :cols => 50, :rows => 2, :class => 'autogrow' %> 4 + <%= form_remote_tag :url => {:controller => 'profile', :action => 'leave_scrap', :tab_action => 'wall' }, :update => 'profile_activities', :success => "jQuery('#leave_scrap_content').val(''); jQuery('#filter-followed').tokenInput('clear')", :complete => "jQuery('#leave_scrap_form').removeClass('loading').find('*').attr('disabled', false)", :loading => "jQuery('#leave_scrap_form').addClass('loading').find('*').attr('disabled', true)", :html => {:id => 'leave_scrap_form' } do %>
  5 + <%= limited_text_area :scrap, :content, 420, 'leave_scrap_content', :rows => 2, :class => 'autogrow' %>
  6 + <% if profile == user %>
  7 + <%= token_input_field_tag(:filter_followed, 'filter-followed', {:action => 'search_followed'}, {:theme => 'facebook', :placeholder => _('Filter followed, friends or group of friends to send them a private scrap...')}) %>
  8 + <% end %>
6 <%= submit_button :new, _('Share') %> 9 <%= submit_button :new, _('Share') %>
7 <% end %> 10 <% end %>
8 </div> 11 </div>
app/views/profile/send_mail.html.erb
@@ -22,8 +22,7 @@ @@ -22,8 +22,7 @@
22 22
23 <%= labelled_form_field(_('Subject:'), f.text_field(:subject)) %> 23 <%= labelled_form_field(_('Subject:'), f.text_field(:subject)) %>
24 24
25 - <%= render :file => 'shared/tiny_mce' %>  
26 - <%= labelled_form_field(_('Body:'), f.text_area(:body, :class => 'mceEditor')) %> 25 + <%= labelled_form_field(_('Body:'), f.text_area(:body, :class => 'body ' + current_editor)) %>
27 26
28 <%= submit_button(:send, _('Send')) %> 27 <%= submit_button(:send, _('Send')) %>
29 <%= button :cancel, _('Cancel e-mail'), :back %> 28 <%= button :cancel, _('Cancel e-mail'), :back %>
app/views/profile_editor/_pending_tasks.html.erb
@@ -2,9 +2,9 @@ @@ -2,9 +2,9 @@
2 2
3 <% unless @pending_tasks.empty? %> 3 <% unless @pending_tasks.empty? %>
4 <div class='pending-tasks'> 4 <div class='pending-tasks'>
5 - <h2><%= _('You have pending requests') %></h2> 5 + <h2><%= _('You have %s pending requests' % @pending_tasks.count) %></h2>
6 <ul> 6 <ul>
7 - <%= safe_join(@pending_tasks.map {|task| content_tag('li', task_information(task).html_safe)}) %> 7 + <%= safe_join(@pending_tasks.limit(5).map {|task| content_tag('li', task_information(task, params).html_safe)}) %>
8 </ul> 8 </ul>
9 <%= button(:todo, _('Process requests'), :controller => 'tasks', :action => 'index') %> 9 <%= button(:todo, _('Process requests'), :controller => 'tasks', :action => 'index') %>
10 </div> 10 </div>
app/views/profile_editor/_person.html.erb
@@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
16 </div> 16 </div>
17 </div> 17 </div>
18 18
  19 + <%= select_editor(_('Editor'), 'profile_data', 'editor', {}) %>
  20 +
19 <%= safe_join(@plugins.dispatch(:profile_info_extra_contents).collect { |content| instance_exec(&content) }, "") %> 21 <%= safe_join(@plugins.dispatch(:profile_info_extra_contents).collect { |content| instance_exec(&content) }, "") %>
20 22
21 <div class="formfieldline"> 23 <div class="formfieldline">
app/views/profile_editor/header_footer.html.erb
1 -<%= render :file => 'shared/tiny_mce' %>  
2 -  
3 <h1><%= _('Editing header and footer') %></h1> 1 <h1><%= _('Editing header and footer') %></h1>
4 2
5 <%= form_tag do %> 3 <%= form_tag do %>
@@ -21,9 +19,9 @@ @@ -21,9 +19,9 @@
21 </div> 19 </div>
22 <% end %> 20 <% end %>
23 <h2><%= _('Content for header ') %></h2> 21 <h2><%= _('Content for header ') %></h2>
24 - <%= text_area_tag(:custom_header, @header, :style => 'width: 100%; height: 150px;', :class => 'mceEditor') %> 22 + <%= text_area_tag(:custom_header, @header, :style => 'width: 100%; height: 150px;', :class => current_editor) %>
25 <h2><%= _('Content for footer') %></h2> 23 <h2><%= _('Content for footer') %></h2>
26 - <%= text_area_tag(:custom_footer, @footer, :style => 'width: 100%; height: 150px;', :class => 'mceEditor') %> 24 + <%= text_area_tag(:custom_footer, @footer, :style => 'width: 100%; height: 150px;', :class => current_editor) %>
27 <%= button_bar do %> 25 <%= button_bar do %>
28 <%= submit_button(:save, _('Save')) %> 26 <%= submit_button(:save, _('Save')) %>
29 <%= button(:cancel, _('Cancel'), :action => 'index') %> 27 <%= button(:cancel, _('Cancel'), :action => 'index') %>
app/views/profile_editor/welcome_page.html.erb
@@ -8,7 +8,7 @@ @@ -8,7 +8,7 @@
8 <%= _('Your welcome page will only be displayed if this options is selected.') %> 8 <%= _('Your welcome page will only be displayed if this options is selected.') %>
9 </div> 9 </div>
10 10
11 - <%= f.text_area(:body, :cols => 40, :style => 'width: 100%', :class => 'mceEditor') %> 11 + <%= f.text_area(:body, :cols => 40, :style => 'width: 100%', :class => current_editor) %>
12 <div class='explanation'> 12 <div class='explanation'>
13 <%= _('This page will be displayed to the user after his signup with this template.') %> 13 <%= _('This page will be displayed to the user after his signup with this template.') %>
14 </div> 14 </div>
@@ -17,5 +17,3 @@ @@ -17,5 +17,3 @@
17 <%= submit_button('save', _('Save'), :cancel => @back_to) %> 17 <%= submit_button('save', _('Save'), :cancel => @back_to) %>
18 <% end %> 18 <% end %>
19 <% end %> 19 <% end %>
20 -  
21 -<%= render :file => 'shared/tiny_mce' %>  
app/views/shared/_lead_and_body.html.erb
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 <% abstract_method ||= :abstract %> 3 <% abstract_method ||= :abstract %>
4 <% body_label ||= 'Text' %> 4 <% body_label ||= 'Text' %>
5 <% body_method ||= :body %> 5 <% body_method ||= :body %>
6 -<% editor_type = defined?(tiny_mce) && tiny_mce ? 'mceEditor' : '' %> 6 +<% editor_type = current_editor %>
7 <% lead_id ||= 0%> 7 <% lead_id ||= 0%>
8 <% f ||= false%> 8 <% f ||= false%>
9 9
app/views/shared/_profile_connections.html.erb
@@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
4 <ul class="profile-list"> 4 <ul class="profile-list">
5 <% profiles.each do |profile| %> 5 <% profiles.each do |profile| %>
6 <li> 6 <li>
7 - <%= link_to_profile profile_image(profile) + '<br/>' + profile.short_name, 7 + <%= link_to_profile profile_image(profile) + '<br/>'.html_safe + profile.short_name,
8 profile.identifier, :class => 'profile-link' %> 8 profile.identifier, :class => 'profile-link' %>
9 </li> 9 </li>
10 <% end %> 10 <% end %>
app/views/shared/logged_in/xmpp_chat.html.erb
1 - <%= javascript_include_tag 'strophejs-1.1.3/strophe.min', 'jquery.emoticon', 'designs/icons/pidgin/emoticons.js', 'ba-linkify', 'jquery.ba-hashchange', 'jquery.sound', 'chat', 'vendor/perfect-scrollbar.min.js', 'vendor/perfect-scrollbar.with-mousewheel.min.js', 'jquery.timeago.js' %> 1 + <%= javascript_include_tag 'vendor/strophejs-1.1.3/strophe.min', 'vendor/jquery.emoticon', 'designs/icons/pidgin/emoticons.js', 'vendor/ba-linkify', 'vendor/jquery.ba-hashchange', 'vendor/jquery.sound', 'chat', 'vendor/perfect-scrollbar.min.js', 'vendor/perfect-scrollbar.with-mousewheel.min.js', 'vendor/jquery.timeago.js' %>
2 <%= stylesheet_link_tag 'vendor/perfect-scrollbar.min.css' %> 2 <%= stylesheet_link_tag 'vendor/perfect-scrollbar.min.css' %>
3 3
4 <% extend ChatHelper %> 4 <% extend ChatHelper %>
app/views/shared/not_found.html.erb
1 <div id='not-found'> 1 <div id='not-found'>
2 - <h1><%= _('There is no such page: %s') % (content_tag('tt', @path)) %></h1> 2 + <h1><%= _('There is no such page: %s').html_safe % (content_tag('tt', @path)) %></h1>
3 <p> 3 <p>
4 <%= _('.You may have clicked an expired link or mistyped the address.') %> 4 <%= _('.You may have clicked an expired link or mistyped the address.') %>
5 <%= _('.This page does not exist. Would you like to: Create a new content or locate existing content.') %> 5 <%= _('.This page does not exist. Would you like to: Create a new content or locate existing content.') %>
app/views/shared/tiny_mce.html.erb
@@ -47,7 +47,9 @@ function tinymce_macros_setup(editor) { @@ -47,7 +47,9 @@ function tinymce_macros_setup(editor) {
47 tinymce.PluginManager.add('macrosPlugin', tinymce.plugins.MacrosPlugin); 47 tinymce.PluginManager.add('macrosPlugin', tinymce.plugins.MacrosPlugin);
48 48
49 jQuery(document).ready(function () { 49 jQuery(document).ready(function () {
50 - <%= tinymce_init_js :mode => mode %> 50 + <%= tinymce_init_js %>
  51 + <%= tinymce_init_js :mode => 'simple' %>
  52 + <%= tinymce_init_js :mode => 'restricted' %>
51 }); 53 });
52 </script> 54 </script>
53 55