Commit 03e2965e2112c154ee2e7f4c75db3af04a1c49f0
Exists in
master
and in
29 other branches
Merge branches 'master' and 'AI3269_link-article' into AI3269_link-article
Showing
1485 changed files
with
91831 additions
and
157969 deletions
Show diff stats
Too many changes.
To preserve performance only 100 of 1485 files displayed.
.ackrc
AUTHORS
@@ -1,250 +0,0 @@ | @@ -1,250 +0,0 @@ | ||
1 | -If you are not listed here, but should be, please write to the noosfero mailing | ||
2 | -list: http://listas.softwarelivre.org/cgi-bin/mailman/listinfo/noosfero-dev | ||
3 | -(this list requires subscription to post, but since you are an author of | ||
4 | -noosfero, that's not a problem). | ||
5 | - | ||
6 | -Developers | ||
7 | -========== | ||
8 | - | ||
9 | -Ábner Silva de Oliveira <abner.oliveira@serpro.gov.br> | ||
10 | -Alan Freihof Tygel <alantygel@gmail.com> | ||
11 | -alcampelo <alcampelo@alcampelo.(none)> | ||
12 | -Alessandro Palmeira <alessandro.palmeira@gmail.com> | ||
13 | -Alessandro Palmeira + Caio C. Salgado <alessandro.palmeira@gmail.com> | ||
14 | -Alessandro Palmeira + Caio Salgado <alessandro.palmeira@gmail.com> | ||
15 | -Alessandro Palmeira + Caio Salgado <caio.csalgado@gmail.com> | ||
16 | -Alessandro Palmeira + Caio Salgado + Diego Araújo + João M. M. da Silva <diegoamc90@gmail.com> | ||
17 | -Alessandro Palmeira + Carlos Morais <alessandro.palmeira@gmail.com> | ||
18 | -Alessandro Palmeira + Daniel Alves <alessandro.palmeira@gmail.com> | ||
19 | -Alessandro Palmeira + Daniel Alves + Diego Araújo <diegoamc90@gmail.com> | ||
20 | -Alessandro Palmeira + Daniel Alves + Diego Araújo + Guilherme Rojas <danpaulalves@gmail.com> | ||
21 | -Alessandro Palmeira + Diego Araujo <alessandro.palmeira@gmail.com> | ||
22 | -Alessandro Palmeira + Diego Araújo <alessandro.palmeira@gmail.com> | ||
23 | -Alessandro Palmeira + Diego Araujo + Daniela Feitosa <alessandro.palmeira@gmail.com> | ||
24 | -Alessandro Palmeira + Diego Araujo <diegoamc90@gmail.com> | ||
25 | -Alessandro Palmeira + Diego Araújo <diegoamc90@gmail.com> | ||
26 | -Alessandro Palmeira + Diego Araujo + Eduardo Morais <alessandro.palmeira@gmail.com> | ||
27 | -Alessandro Palmeira + Diego Araújo + João M. M. da Silva <alessandro.palmeira@gmail.com> | ||
28 | -Alessandro Palmeira + Diego Araújo + João M. M. da Silva <diegoamc90@gmail.com> | ||
29 | -Alessandro Palmeira + Diego Araujo + João M. M. da Silva + Paulo Meirelles <alessandro.palmeira@gmail.com> | ||
30 | -Alessandro Palmeira + Diego Araújo + Pedro Leal <diegoamc90@gmail.com> | ||
31 | -Alessandro Palmeira + Diego Araújo + Pedro Leal + João M. M. da Silva <diegoamc90@gmail.com> | ||
32 | -Alessandro Palmeira + Diego Araujo + Rafael Manzo <alessandro.palmeira@gmail.com> | ||
33 | -Alessandro Palmeira + Eduardo Morais <alessandro.palmeira@gmail.com> | ||
34 | -Alessandro Palmeira + Guilherme Rojas <alessandro.palmeira@gmail.com> | ||
35 | -Alessandro Palmeira + Jefferson Fernandes <alessandro.palmeira@gmail.com> | ||
36 | -Alessandro Palmeira + João M. M. da Silva <alessandro.palmeira@gmail.com> | ||
37 | -Alessandro Palmeira + Joao M. M. da Silva + Diego Araujo <alessandro.palmeira@gmail.com> | ||
38 | -Alessandro Palmeira + João M. M. da Silva + Renan Teruo <alessandro.palmeira@gmail.com> | ||
39 | -Alessandro Palmeira + João M. M. Silva <alessandro.palmeira@gmail.com> | ||
40 | -Alessandro Palmeira + Paulo Meirelles <alessandro.palmeira@gmail.com> | ||
41 | -Alessandro Palmeira + Paulo Meirelles + João M. M. da Silva <alessandro.palmeira@gmail.com> | ||
42 | -Alessandro Palmeira + Rafael Manzo <alessandro.palmeira@gmail.com> | ||
43 | -Ana Losnak <analosnak@gmail.com> | ||
44 | -Antonio Terceiro + Carlos Morais <terceiro@colivre.coop.br> | ||
45 | -Antonio Terceiro + Paulo Meirelles <terceiro@colivre.coop.br> | ||
46 | -Antonio Terceiro <terceiro@colivre.coop.br> | ||
47 | -Arthur Del Esposte <arthurmde@gmail.com> | ||
48 | -Arthur Del Esposte <arthurmde@yahoo.com.br> | ||
49 | -Aurelio A. Heckert <aurelio@colivre.coop.br> | ||
50 | -Braulio Bhavamitra <brauliobo@gmail.com> | ||
51 | -Bráulio Bhavamitra <brauliobo@gmail.com> | ||
52 | -Braulio Bhavamitra <braulio@eita.org.br> | ||
53 | -Caio <caio.csalgado@gmail.com> | ||
54 | -Caio + Diego + Pedro + João <caio.csalgado@gmail.com> | ||
55 | -Caio Formiga <caio.formiga@gmail.com> | ||
56 | -Caio, Pedro <caio.csalgado@gmail.com> | ||
57 | -Caio Salgado + Alessandro Palmeira <caio.csalgado@gmail.com> | ||
58 | -Caio Salgado <caio.csalgado@gmail.com> | ||
59 | -Caio Salgado + Carlos Morais + Diego Araújo + Pedro Leal <diegoamc90@gmail.com> | ||
60 | -Caio Salgado + Diego Araujo <caio.csalgado@gmail.com> | ||
61 | -Caio Salgado + Diego Araújo <caio.csalgado@gmail.com> | ||
62 | -Caio Salgado + Diego Araújo <diegoamc90@gmail.com> | ||
63 | -Caio Salgado + Diego Araújo + Jefferson Fernandes <caio.csalgado@gmail.com> | ||
64 | -Caio Salgado + Diego Araújo + João M. M. da Silva <caio.csalgado@gmail.com> | ||
65 | -Caio Salgado + Diego Araújo + Pedro Leal <caio.csalgado@gmail.com> | ||
66 | -Caio Salgado + Diego Araújo + Pedro Leal <diegoamc90@gmail.com> | ||
67 | -Caio Salgado + Diego Araújo + Rafael Manzo <diegoamc90@gmail.com> | ||
68 | -Caio Salgado + Jefferson Fernandes <caio.csalgado@gmail.com> | ||
69 | -Caio Salgado + Jefferson Fernandes <jeffs.fernandes@gmail.com> | ||
70 | -Caio Salgado + Rafael Manzo <caio.csalgado@gmail.com> | ||
71 | -Caio Salgado + Renan Teruo <caio.csalgado@gmail.com> | ||
72 | -Caio Salgado + Renan Teruo <caio.salgado@gmail.com> | ||
73 | -Caio Salgado + Renan Teruo + Jefferson Fernandes <jeffs.fernandes@gmail.com> | ||
74 | -Caio Salgado + Renan Teruo <renanteruoc@gmail.com> | ||
75 | -Caio SBA <caio@colivre.coop.br> | ||
76 | -Caio Tiago Oliveira <caiotiago@colivre.coop.br> | ||
77 | -Carlos Andre de Souza <carlos.andre.souza@msn.com> | ||
78 | -Carlos Morais <carlos88morais@gmail.com> | ||
79 | -Carlos Morais + Diego Araújo <diegoamc90@gmail.com> | ||
80 | -Carlos Morais + Eduardo Morais <carlos88morais@gmail.com> | ||
81 | -Carlos Morais + Paulo Meirelles <carlos88morais@gmail.com> | ||
82 | -Carlos Morais + Pedro Leal <carlos88morais@gmail.com> | ||
83 | -Daniela Feitosa <dani@dohko.(none)> | ||
84 | -Daniel Alves + Diego Araújo <danpaulalves@gmail.com> | ||
85 | -Daniel Alves + Diego Araújo <diegoamc90@gmail.com> | ||
86 | -Daniel Alves + Diego Araújo + Guilherme Rojas <danpaulalves@gmail.com> | ||
87 | -Daniel Alves + Diego Araújo + Guilherme Rojas <diegoamc90@gmail.com> | ||
88 | -Daniel Alves + Diego Araújo + Guilherme Rojas <guilhermehrojas@gmail.com> | ||
89 | -Daniel Alves + Guilherme Rojas <danpaulalves@gmail.com> | ||
90 | -Daniel Alves + Rafael Manzo <rr.manzo@gmail.com> | ||
91 | -Daniela Soares Feitosa <danielafeitosa@colivre.coop.br> | ||
92 | -Daniel Bucher <daniel.bucher88@gmail.com> | ||
93 | -Daniel Cunha <daniel@colivre.coop.br> | ||
94 | -David Carlos <ddavidcarlos1392@gmail.com> | ||
95 | -diegoamc <diegoamc90@gmail.com> | ||
96 | -Diego Araújo + Alessandro Palmeira <diegoamc90@gmail.com> | ||
97 | -Diego Araújo + Alessandro Palmeira + João M. M. da Silva <diegoamc90@gmail.com> | ||
98 | -Diego Araújo + Alessandro Palmeira + Rafael Manzo <rr.manzo@gmail.com> | ||
99 | -Diego Araujo + Caio Salgado <diegoamc90@gmail.com> | ||
100 | -Diego Araújo + Daniel Alves + Rafael Manzo <rr.manzo@gmail.com> | ||
101 | -Diego Araújo <diegoamc90@gmail.com> | ||
102 | -Diego Araújo + Eduardo Morais + Paulo Meirelles <diegoamc90@gmail.com> | ||
103 | -Diego Araújo + Guilherme Rojas <diegoamc90@gmail.com> | ||
104 | -Diego Araújo + Jefferson Fernandes <diegoamc90@gmail.com> | ||
105 | -Diego Araujo + Jefferson Fernandes <jeffs.fernandes@gmail.com> | ||
106 | -Diego Araújo + João Machini <diegoamc90@gmail.com> | ||
107 | -Diego Araújo + João Machini <digoamc90@gmail.com> | ||
108 | -Diego Araújo + João M. M. da Silva + Alessandro Palmeira <jaodsilv@linux.ime.usp.br> | ||
109 | -Diego Araújo + João M. M. da Silva <diegoamc90@gmail.com> | ||
110 | -Diego Araújo + João M. M. da Silva + João Machini <diegoamc90@gmail.com> | ||
111 | -Diego Araújo + João M. M. da Silva + Pedro Leal <diegoamc90@gmail.com> | ||
112 | -Diego Araújo + Paulo Meirelles <diegoamc90@gmail.com> | ||
113 | -Diego Araújo + Pedro Leal <diegoamc90@gmail.com> | ||
114 | -Diego Araujo + Rafael Manzo <diegoamc90@gmail.com> | ||
115 | -Diego Araújo + Rafael Manzo <diegoamc90@gmail.com> | ||
116 | -Diego Araújo + Renan Teruo + Alessandro Palmeira <diegoamc90@gmail.com> | ||
117 | -Diego Araújo + Renan Teruo <diegoamc90@gmail.com> | ||
118 | -Diego Araujo + Rodrigo Souto + Rafael Manzo <rr.manzo@gmail.com> | ||
119 | -Diego + Jefferson <diegoamc90@gmail.com> | ||
120 | -Diego Martinez <diegoamc90@gmail.com> | ||
121 | -Diego Martinez <diego@diego-K55A.(none)> | ||
122 | -Diego + Renan <renanteruoc@gmail.com> | ||
123 | -Eduardo Tourinho Edington <eduardo.edington@serpro.gov.br> | ||
124 | -Evandro Jr <evandrojr@gmail.com> | ||
125 | -Evandro Junior <evandrojr@gmail.com> | ||
126 | -Fabio Teixeira <fabio1079@gmail.com> | ||
127 | -Fernanda Lopes <nanda.listas+psl@gmail.com> | ||
128 | -Francisco Marcelo A. Lima Júnior <francisco.lima-junior@serpro.gov.br> | ||
129 | -Francisco Marcelo de Araujo Lima Junior <79350259591@serpro-1457614.(none)> | ||
130 | -Francisco Marcelo de Araújo Lima Júnior <francisco.lima-junior@serpro.gov.br> | ||
131 | -Francisco Marcelo de Araújo Lima Júnior <maljunior@gmail.com> | ||
132 | -Gabriela Navarro <navarro1703@gmail.com> | ||
133 | -Grazieno Pellegrino <grazieno@gmail.com> | ||
134 | -Gust <darksshades@hotmail.com> | ||
135 | -Hugo Melo <hugo@riseup.net> | ||
136 | -Isaac Canan <isaac@intelletto.com.br> | ||
137 | -Italo Valcy <italo@dcc.ufba.br> | ||
138 | -Jefferson Fernandes + Diego Araujo + Rafael Manzo <jeffs.fernandes@gmail.com> | ||
139 | -Jefferson Fernandes + Joao M. M. da Silva <jeffs.fernandes@gmail.com> | ||
140 | -Jefferson Fernandes + Joao M. M. Silva <jeffs.fernandes@gmail.com> | ||
141 | -João da Silva + Eduardo Morais + Rafael Manzo <rr.manzo@gmail.com> | ||
142 | -João da Silva <jaodsilv@linux.ime.usp.br> | ||
143 | -João Marco Maciel da Silva + Rafael Manzo + Renan Teruo <jaodsilv@linux.ime.usp.br> | ||
144 | -João M. M. da Silva + Alessandro Palmeira + Diego Araújo + Caio Salgado <jaodsilv@linux.ime.usp.br> | ||
145 | -João M. M. da Silva + Alessandro Palmeira + Diego Araújo <jaodsilv@linux.ime.usp.br> | ||
146 | -Joao M. M. da Silva + Alessandro Palmeira <jaodsilv@linux.ime.usp.br> | ||
147 | -João M. M. da Silva + Alessandro Palmeira <jaodsilv@linux.ime.usp.br> | ||
148 | -João M. M. da Silva + Alessandro Palmeira + João Machini <jaodsilv@linux.ime.usp.br> | ||
149 | -João M. M. da Silva + Caio Salgado + Alessandro Palmeira <jaodsilv@linux.ime.usp.br> | ||
150 | -João M. M. da Silva + Caio Salgado <jaodsilv@linux.ime.usp.br> | ||
151 | -João M. M. da Silva + Carlos Morais <jaodsilv@linux.ime.usp.br> | ||
152 | -João M. M. da Silva + Diego Araújo <diegoamc90@gmail.com> | ||
153 | -João M. M. da Silva + Diego Araújo <jaodsilv@linux.ime.usp.br> | ||
154 | -João M. M. da Silva + Diego Araújo + Pedro Leal <jaodsilv@linux.ime.usp.br> | ||
155 | -João M. M. da Silva <jaodsilv@linux.ime.usp.br> | ||
156 | -Joao M. M. da Silva + Jefferson Fernandes <jaodsilv@linux.ime.usp.br> | ||
157 | -João M. M. da Silva + Jefferson Fernandes <jaodsilv@linux.ime.usp.br> | ||
158 | -João M. M. da Silva + João M. Miranda <jaodsilv@linux.ime.usp.br> | ||
159 | -João M. M. da Silva + Paulo Meirelles <jaodsilv@linux.ime.usp.br> | ||
160 | -João M. M. da Silva + Pedro Leal <jaodsilv@linux.ime.usp.br> | ||
161 | -João M. M. da Silva + Rafael Manzo + Diego Araújo <jaodsilv@linux.ime.usp.br> | ||
162 | -João M. M. da Silva + Rafael Manzo <jaodsilv@linux.ime.usp.br> | ||
163 | -João M. M. da Silva + Renan Teruo <jaodsilv@linux.ime.usp.br> | ||
164 | -João M. M. Silva + Caio Salgado <jaodsilv@linux.ime.usp.br> | ||
165 | -João M. M. Silva + Diego Araújo <jaodsilv@linux.ime.usp.br> | ||
166 | -Joao M. M. Silva + Jefferson Fernandes <jaodsilv@linux.ime.usp.br> | ||
167 | -João M. M. Silva + Paulo Meirelles <jaodsilv@linux.ime.usp.br> | ||
168 | -João M. M. Silva + Rafael Manzo <jaodsilv@linux.ime.usp.br> | ||
169 | -João M. M. Silva + Renan Teruo <jaodsilv@linux.ime.usp.br> | ||
170 | -Joenio Costa <joenio@colivre.coop.br> | ||
171 | -Josef Spillner <josef.spillner@tu-dresden.de> | ||
172 | -Junior Silva <junior@bajor.localhost.localdomain> | ||
173 | -Junior Silva <juniorsilva1001@gmail.com> | ||
174 | -Junior Silva <juniorsilva7@juniorsilva-Aspire-5750Z.(none)> | ||
175 | -Junior Silva <juniorsilva@colivre.coop.br> | ||
176 | -juniorsilva <juniorsilva@QonoS.localhost.localdomain> | ||
177 | -Keilla Menezes <keilla@colivre.coop.br> | ||
178 | -Larissa Reis <larissa@colivre.coop.br> | ||
179 | -Larissa Reis <reiss.larissa@gmail.com> | ||
180 | -Leandro Nunes dos Santos <81665687568@serpro-1541727.Home> | ||
181 | -Leandro Nunes dos Santos <81665687568@serpro-1541727.(none)> | ||
182 | -Leandro Nunes dos Santos <leandronunes@gmail.com> | ||
183 | -Leandro Nunes dos Santos <leandro.santos@serpro.gov.br> | ||
184 | -LinguÁgil 2010 <linguagil.bahia@gmail.com> | ||
185 | -Lucas Melo <lucas@colivre.coop.br> | ||
186 | -Lucas Melo <lucaspradomelo@gmail.com> | ||
187 | -Luciano <lucianopcbr@gmail.com> | ||
188 | -Luis David Aguilar Carlos <ludwig9003@gmail.com> | ||
189 | -Luiz Fernando de Freitas Matos <luiz@luizff.matos@gmail.com> | ||
190 | -Marcos Ramos <ms.ramos@outlook.com> | ||
191 | -Martín Olivera <molivera@solar.org.ar> | ||
192 | -Moises Machado <moises@colivre.coop.br> | ||
193 | -Naíla Alves <naila@colivre.coop.br> | ||
194 | -Nanda Lopes <nanda.listas+psl@gmail.com> | ||
195 | -Paulo Meirelles + Alessandro Palmeira + João M. M. da Silva <paulo@softwarelivre.org> | ||
196 | -Paulo Meirelles + Alessandro Palmeira <paulo@softwarelivre.org> | ||
197 | -Paulo Meirelles + Carlos Morais <paulo@softwarelivre.org> | ||
198 | -Paulo Meirelles + Diego Araújo <paulo@softwarelivre.org> | ||
199 | -Paulo Meirelles + João M. M. da Silva <paulo@softwarelivre.org> | ||
200 | -Paulo Meirelles <paulo@softwarelivre.org> | ||
201 | -Paulo Meirelles + Rafael Manzo <paulo@softwarelivre.org> | ||
202 | -Rafael Gomes <rafaelgomes@techfree.com.br> | ||
203 | -Rafael Manzo + Alessandro Palmeira <rr.manzo@gmail.com> | ||
204 | -Rafael Manzo + Daniel Alves <danpaulalves@gmail.com> | ||
205 | -Rafael Manzo + Diego Araújo <rr.manzo@gmail.com> | ||
206 | -Rafael Manzo + João M. M. Silva <rr.manzo@gmail.com> | ||
207 | -Rafael Manzo + Paulo Meirelles <rr.manzo@gmail.com> | ||
208 | -Rafael Martins <rmmartins@gmail.com> | ||
209 | -Rafael Reggiani Manzo + Caio Salgado + Jefferson Fernandes <rr.manzo@gmail.com> | ||
210 | -Rafael Reggiani Manzo + Diego Araujo <diegoamc90@gmail.com> | ||
211 | -Rafael Reggiani Manzo + Diego Araujo <rr.manzo@gmail.com> | ||
212 | -Rafael Reggiani Manzo + Diego Araújo <rr.manzo@gmail.com> | ||
213 | -Rafael Reggiani Manzo + João M. M. da Silva <rr.manzo@gmail.com> | ||
214 | -Rafael Reggiani Manzo <rr.manzo@gmail.com> | ||
215 | -Raphaël Rousseau <raph@r4f.org> | ||
216 | -Raquel Lira <raquel.lira@gmail.com> | ||
217 | -Renan Teruo + Caio Salgado <renanteruoc@gmail.com> | ||
218 | -Renan Teruoc + Diego Araujo <renanteruoc@gmail.com> | ||
219 | -Renan Teruo + Diego Araujo <renanteruoc@gmail.com> | ||
220 | -Renan Teruo + Diego Araújo <renanteruoc@gmail.com> | ||
221 | -Renan Teruo + Paulo Meirelles <renanteruoc@gmail.com> | ||
222 | -Renan Teruo + Rafael Manzo <renanteruoc@gmail.com> | ||
223 | -Rodrigo Souto + Ana Losnak + Daniel Bucher + Caio Almeida + Leandro Nunes + Daniela Feitosa + Mariel Zasso <noosfero-br@listas.softwarelivre.org> | ||
224 | -Rodrigo Souto <diguliu@gmail.com> | ||
225 | -Rodrigo Souto <rodrigo@colivre.coop.br> | ||
226 | -Ronny Kursawe <kursawe.ronny@googlemail.com> | ||
227 | -root <root@debian.sdr.serpro> | ||
228 | -Samuel R. C. Vale <srcvale@holoscopio.com> | ||
229 | -Valessio Brito <contato@valessiobrito.com.br> | ||
230 | -Valessio Brito <contato@valessiobrito.info> | ||
231 | -Valessio Brito <valessio@gmail.com> | ||
232 | -vfcosta <vfcosta@gmail.com> | ||
233 | -Victor Carvalho <victorhugodf.ac@gmail.com> | ||
234 | -Victor Costa <vfcosta@gmail.com> | ||
235 | -Victor Hugo Alves de Carvalho <victorhugodf.ac@gmail.com> | ||
236 | -Vinicius Cubas Brand <viniciuscb@gmail.com> | ||
237 | -Visita <visita@debian.(none)> | ||
238 | -Yann Lugrin <yann.lugrin@liquid-concept.ch> | ||
239 | - | ||
240 | -Ideas, specifications and incentive | ||
241 | -=================================== | ||
242 | -Daniel Tygel <dtygel@fbes.org.br> | ||
243 | -Guilherme Rocha <guilherme@gf7.com.br> | ||
244 | -Raphael Rousseau <raph@r4f.org> | ||
245 | -Théo Bondolfi <move@cooperation.net> | ||
246 | -Vicente Aguiar <vicenteaguiar@colivre.coop.br> | ||
247 | - | ||
248 | -Arts | ||
249 | -=================================== | ||
250 | -Nara Oliveira <narananet@gmail.com> |
AUTHORS.md
1 | -If you are not listed here, but should be, please write to the noosfero mailing list: http://listas.softwarelivre.org/cgi-bin/mailman/listinfo/noosfero-dev (this list requires subscription to post, but since you are an author of noosfero, that's not a problem). | 1 | +If you are not listed here, but should be, please write to the noosfero mailing |
2 | +list: http://listas.softwarelivre.org/cgi-bin/mailman/listinfo/noosfero-dev | ||
3 | +(this list requires subscription to post, but since you are an author of | ||
4 | +noosfero, that's not a problem). | ||
2 | 5 | ||
3 | Developers | 6 | Developers |
4 | ========== | 7 | ========== |
5 | 8 | ||
9 | +Ábner Silva de Oliveira <abner.oliveira@serpro.gov.br> | ||
6 | Alan Freihof Tygel <alantygel@gmail.com> | 10 | Alan Freihof Tygel <alantygel@gmail.com> |
11 | +alcampelo <alcampelo@alcampelo.(none)> | ||
7 | Alessandro Palmeira <alessandro.palmeira@gmail.com> | 12 | Alessandro Palmeira <alessandro.palmeira@gmail.com> |
8 | Alessandro Palmeira + Caio C. Salgado <alessandro.palmeira@gmail.com> | 13 | Alessandro Palmeira + Caio C. Salgado <alessandro.palmeira@gmail.com> |
9 | Alessandro Palmeira + Caio Salgado <alessandro.palmeira@gmail.com> | 14 | Alessandro Palmeira + Caio Salgado <alessandro.palmeira@gmail.com> |
@@ -35,9 +40,14 @@ Alessandro Palmeira + João M. M. Silva <alessandro.palmeira@gmail.com> | @@ -35,9 +40,14 @@ Alessandro Palmeira + João M. M. Silva <alessandro.palmeira@gmail.com> | ||
35 | Alessandro Palmeira + Paulo Meirelles <alessandro.palmeira@gmail.com> | 40 | Alessandro Palmeira + Paulo Meirelles <alessandro.palmeira@gmail.com> |
36 | Alessandro Palmeira + Paulo Meirelles + João M. M. da Silva <alessandro.palmeira@gmail.com> | 41 | Alessandro Palmeira + Paulo Meirelles + João M. M. da Silva <alessandro.palmeira@gmail.com> |
37 | Alessandro Palmeira + Rafael Manzo <alessandro.palmeira@gmail.com> | 42 | Alessandro Palmeira + Rafael Manzo <alessandro.palmeira@gmail.com> |
43 | +analosnak <analosnak@gmail.com> | ||
44 | +Ana Losnak <analosnak@gmail.com> | ||
45 | +Andre Bernardes <andrebsguedes@gmail.com> | ||
38 | Antonio Terceiro + Carlos Morais <terceiro@colivre.coop.br> | 46 | Antonio Terceiro + Carlos Morais <terceiro@colivre.coop.br> |
39 | Antonio Terceiro + Paulo Meirelles <terceiro@colivre.coop.br> | 47 | Antonio Terceiro + Paulo Meirelles <terceiro@colivre.coop.br> |
40 | Antonio Terceiro <terceiro@colivre.coop.br> | 48 | Antonio Terceiro <terceiro@colivre.coop.br> |
49 | +Arthur Del Esposte <arthurmde@gmail.com> | ||
50 | +Arthur Del Esposte <arthurmde@yahoo.com.br> | ||
41 | Aurelio A. Heckert <aurelio@colivre.coop.br> | 51 | Aurelio A. Heckert <aurelio@colivre.coop.br> |
42 | Braulio Bhavamitra <brauliobo@gmail.com> | 52 | Braulio Bhavamitra <brauliobo@gmail.com> |
43 | Bráulio Bhavamitra <brauliobo@gmail.com> | 53 | Bráulio Bhavamitra <brauliobo@gmail.com> |
@@ -65,6 +75,8 @@ Caio Salgado + Renan Teruo <caio.salgado@gmail.com> | @@ -65,6 +75,8 @@ Caio Salgado + Renan Teruo <caio.salgado@gmail.com> | ||
65 | Caio Salgado + Renan Teruo + Jefferson Fernandes <jeffs.fernandes@gmail.com> | 75 | Caio Salgado + Renan Teruo + Jefferson Fernandes <jeffs.fernandes@gmail.com> |
66 | Caio Salgado + Renan Teruo <renanteruoc@gmail.com> | 76 | Caio Salgado + Renan Teruo <renanteruoc@gmail.com> |
67 | Caio SBA <caio@colivre.coop.br> | 77 | Caio SBA <caio@colivre.coop.br> |
78 | +Caio Tiago Oliveira <caiotiago@colivre.coop.br> | ||
79 | +Carlos Andre de Souza <carlos.andre.souza@msn.com> | ||
68 | Carlos Morais <carlos88morais@gmail.com> | 80 | Carlos Morais <carlos88morais@gmail.com> |
69 | Carlos Morais + Diego Araújo <diegoamc90@gmail.com> | 81 | Carlos Morais + Diego Araújo <diegoamc90@gmail.com> |
70 | Carlos Morais + Eduardo Morais <carlos88morais@gmail.com> | 82 | Carlos Morais + Eduardo Morais <carlos88morais@gmail.com> |
@@ -78,7 +90,9 @@ Daniel Alves + Diego Araújo + Guilherme Rojas <guilhermehrojas@gmail.com> | @@ -78,7 +90,9 @@ Daniel Alves + Diego Araújo + Guilherme Rojas <guilhermehrojas@gmail.com> | ||
78 | Daniel Alves + Guilherme Rojas <danpaulalves@gmail.com> | 90 | Daniel Alves + Guilherme Rojas <danpaulalves@gmail.com> |
79 | Daniel Alves + Rafael Manzo <rr.manzo@gmail.com> | 91 | Daniel Alves + Rafael Manzo <rr.manzo@gmail.com> |
80 | Daniela Soares Feitosa <danielafeitosa@colivre.coop.br> | 92 | Daniela Soares Feitosa <danielafeitosa@colivre.coop.br> |
93 | +Daniel Bucher <daniel.bucher88@gmail.com> | ||
81 | Daniel Cunha <daniel@colivre.coop.br> | 94 | Daniel Cunha <daniel@colivre.coop.br> |
95 | +David Carlos <ddavidcarlos1392@gmail.com> | ||
82 | diegoamc <diegoamc90@gmail.com> | 96 | diegoamc <diegoamc90@gmail.com> |
83 | Diego Araújo + Alessandro Palmeira <diegoamc90@gmail.com> | 97 | Diego Araújo + Alessandro Palmeira <diegoamc90@gmail.com> |
84 | Diego Araújo + Alessandro Palmeira + João M. M. da Silva <diegoamc90@gmail.com> | 98 | Diego Araújo + Alessandro Palmeira + João M. M. da Silva <diegoamc90@gmail.com> |
@@ -105,17 +119,27 @@ Diego Araújo + Renan Teruo <diegoamc90@gmail.com> | @@ -105,17 +119,27 @@ Diego Araújo + Renan Teruo <diegoamc90@gmail.com> | ||
105 | Diego Araujo + Rodrigo Souto + Rafael Manzo <rr.manzo@gmail.com> | 119 | Diego Araujo + Rodrigo Souto + Rafael Manzo <rr.manzo@gmail.com> |
106 | Diego + Jefferson <diegoamc90@gmail.com> | 120 | Diego + Jefferson <diegoamc90@gmail.com> |
107 | Diego Martinez <diegoamc90@gmail.com> | 121 | Diego Martinez <diegoamc90@gmail.com> |
108 | -Diego Martinez <diego@diego-K55A.(none)> | ||
109 | Diego + Renan <renanteruoc@gmail.com> | 122 | Diego + Renan <renanteruoc@gmail.com> |
123 | +Eduardo Tourinho Edington <eduardo.edington@serpro.gov.br> | ||
124 | +Evandro Jr <evandrojr@gmail.com> | ||
125 | +Evandro Junior <evandrojr@gmail.com> | ||
126 | +Fabio Teixeira <fabio1079@gmail.com> | ||
110 | Fernanda Lopes <nanda.listas+psl@gmail.com> | 127 | Fernanda Lopes <nanda.listas+psl@gmail.com> |
111 | Francisco Marcelo A. Lima Júnior <francisco.lima-junior@serpro.gov.br> | 128 | Francisco Marcelo A. Lima Júnior <francisco.lima-junior@serpro.gov.br> |
112 | Francisco Marcelo de Araujo Lima Junior <79350259591@serpro-1457614.(none)> | 129 | Francisco Marcelo de Araujo Lima Junior <79350259591@serpro-1457614.(none)> |
130 | +Francisco Marcelo de Araújo Lima Júnior <francisco.lima-junior@serpro.gov.br> | ||
131 | +Francisco Marcelo de Araújo Lima Júnior <maljunior@gmail.com> | ||
132 | +Gabriela Navarro <navarro1703@gmail.com> | ||
113 | Grazieno Pellegrino <grazieno@gmail.com> | 133 | Grazieno Pellegrino <grazieno@gmail.com> |
134 | +Gust <darksshades@hotmail.com> | ||
135 | +Hebert Douglas <hebertdougl@gmail.com> | ||
136 | +Hugo Melo <hugo@riseup.net> | ||
114 | Isaac Canan <isaac@intelletto.com.br> | 137 | Isaac Canan <isaac@intelletto.com.br> |
115 | Italo Valcy <italo@dcc.ufba.br> | 138 | Italo Valcy <italo@dcc.ufba.br> |
116 | Jefferson Fernandes + Diego Araujo + Rafael Manzo <jeffs.fernandes@gmail.com> | 139 | Jefferson Fernandes + Diego Araujo + Rafael Manzo <jeffs.fernandes@gmail.com> |
117 | Jefferson Fernandes + Joao M. M. da Silva <jeffs.fernandes@gmail.com> | 140 | Jefferson Fernandes + Joao M. M. da Silva <jeffs.fernandes@gmail.com> |
118 | Jefferson Fernandes + Joao M. M. Silva <jeffs.fernandes@gmail.com> | 141 | Jefferson Fernandes + Joao M. M. Silva <jeffs.fernandes@gmail.com> |
142 | +João da Silva + Eduardo Morais + Rafael Manzo <rr.manzo@gmail.com> | ||
119 | João da Silva <jaodsilv@linux.ime.usp.br> | 143 | João da Silva <jaodsilv@linux.ime.usp.br> |
120 | João Marco Maciel da Silva + Rafael Manzo + Renan Teruo <jaodsilv@linux.ime.usp.br> | 144 | João Marco Maciel da Silva + Rafael Manzo + Renan Teruo <jaodsilv@linux.ime.usp.br> |
121 | João M. M. da Silva + Alessandro Palmeira + Diego Araújo + Caio Salgado <jaodsilv@linux.ime.usp.br> | 145 | João M. M. da Silva + Alessandro Palmeira + Diego Araújo + Caio Salgado <jaodsilv@linux.ime.usp.br> |
@@ -146,21 +170,35 @@ João M. M. Silva + Rafael Manzo <jaodsilv@linux.ime.usp.br> | @@ -146,21 +170,35 @@ João M. M. Silva + Rafael Manzo <jaodsilv@linux.ime.usp.br> | ||
146 | João M. M. Silva + Renan Teruo <jaodsilv@linux.ime.usp.br> | 170 | João M. M. Silva + Renan Teruo <jaodsilv@linux.ime.usp.br> |
147 | Joenio Costa <joenio@colivre.coop.br> | 171 | Joenio Costa <joenio@colivre.coop.br> |
148 | Josef Spillner <josef.spillner@tu-dresden.de> | 172 | Josef Spillner <josef.spillner@tu-dresden.de> |
173 | +Jose Pedro <1jpsneto@gmail.com> | ||
174 | +Junior Silva <junior@bajor.localhost.localdomain> | ||
175 | +Junior Silva <junior@sedeantigo.colivre.coop.br> | ||
149 | Junior Silva <juniorsilva1001@gmail.com> | 176 | Junior Silva <juniorsilva1001@gmail.com> |
150 | Junior Silva <juniorsilva7@juniorsilva-Aspire-5750Z.(none)> | 177 | Junior Silva <juniorsilva7@juniorsilva-Aspire-5750Z.(none)> |
178 | +Junior Silva <juniorsilva@colivre.coop.br> | ||
179 | +juniorsilva <juniorsilva@QonoS.localhost.localdomain> | ||
151 | Keilla Menezes <keilla@colivre.coop.br> | 180 | Keilla Menezes <keilla@colivre.coop.br> |
152 | Larissa Reis <larissa@colivre.coop.br> | 181 | Larissa Reis <larissa@colivre.coop.br> |
153 | Larissa Reis <reiss.larissa@gmail.com> | 182 | Larissa Reis <reiss.larissa@gmail.com> |
183 | +Leandro Alves <leandrosustenido@gmail.com> | ||
184 | +Leandro Nunes dos Santos <81665687568@serpro-1541727.Home> | ||
185 | +Leandro Nunes dos Santos <81665687568@serpro-1541727.(none)> | ||
154 | Leandro Nunes dos Santos <leandronunes@gmail.com> | 186 | Leandro Nunes dos Santos <leandronunes@gmail.com> |
155 | Leandro Nunes dos Santos <leandro.santos@serpro.gov.br> | 187 | Leandro Nunes dos Santos <leandro.santos@serpro.gov.br> |
156 | LinguÁgil 2010 <linguagil.bahia@gmail.com> | 188 | LinguÁgil 2010 <linguagil.bahia@gmail.com> |
157 | Lucas Melo <lucas@colivre.coop.br> | 189 | Lucas Melo <lucas@colivre.coop.br> |
158 | Lucas Melo <lucaspradomelo@gmail.com> | 190 | Lucas Melo <lucaspradomelo@gmail.com> |
191 | +Luciano <lucianopcbr@gmail.com> | ||
192 | +Luciano Prestes Cavalcanti <lucianopcbr@gmail.com> | ||
159 | Luis David Aguilar Carlos <ludwig9003@gmail.com> | 193 | Luis David Aguilar Carlos <ludwig9003@gmail.com> |
194 | +Luiz Fernando de Freitas Matos <luiz@luizff.matos@gmail.com> | ||
195 | +Marcos Ramos <ms.ramos@outlook.com> | ||
160 | Martín Olivera <molivera@solar.org.ar> | 196 | Martín Olivera <molivera@solar.org.ar> |
197 | +Michal Čihař <michal@cihar.com> | ||
161 | Moises Machado <moises@colivre.coop.br> | 198 | Moises Machado <moises@colivre.coop.br> |
162 | Naíla Alves <naila@colivre.coop.br> | 199 | Naíla Alves <naila@colivre.coop.br> |
163 | Nanda Lopes <nanda.listas+psl@gmail.com> | 200 | Nanda Lopes <nanda.listas+psl@gmail.com> |
201 | +Parley Martins <parleypachecomartins@gmail.com> | ||
164 | Paulo Meirelles + Alessandro Palmeira + João M. M. da Silva <paulo@softwarelivre.org> | 202 | Paulo Meirelles + Alessandro Palmeira + João M. M. da Silva <paulo@softwarelivre.org> |
165 | Paulo Meirelles + Alessandro Palmeira <paulo@softwarelivre.org> | 203 | Paulo Meirelles + Alessandro Palmeira <paulo@softwarelivre.org> |
166 | Paulo Meirelles + Carlos Morais <paulo@softwarelivre.org> | 204 | Paulo Meirelles + Carlos Morais <paulo@softwarelivre.org> |
@@ -183,20 +221,28 @@ Rafael Reggiani Manzo + João M. M. da Silva <rr.manzo@gmail.com> | @@ -183,20 +221,28 @@ Rafael Reggiani Manzo + João M. M. da Silva <rr.manzo@gmail.com> | ||
183 | Rafael Reggiani Manzo <rr.manzo@gmail.com> | 221 | Rafael Reggiani Manzo <rr.manzo@gmail.com> |
184 | Raphaël Rousseau <raph@r4f.org> | 222 | Raphaël Rousseau <raph@r4f.org> |
185 | Raquel Lira <raquel.lira@gmail.com> | 223 | Raquel Lira <raquel.lira@gmail.com> |
224 | +Raquel <rcordioli@gmail.com> | ||
186 | Renan Teruo + Caio Salgado <renanteruoc@gmail.com> | 225 | Renan Teruo + Caio Salgado <renanteruoc@gmail.com> |
187 | Renan Teruoc + Diego Araujo <renanteruoc@gmail.com> | 226 | Renan Teruoc + Diego Araujo <renanteruoc@gmail.com> |
188 | Renan Teruo + Diego Araujo <renanteruoc@gmail.com> | 227 | Renan Teruo + Diego Araujo <renanteruoc@gmail.com> |
189 | Renan Teruo + Diego Araújo <renanteruoc@gmail.com> | 228 | Renan Teruo + Diego Araújo <renanteruoc@gmail.com> |
190 | Renan Teruo + Paulo Meirelles <renanteruoc@gmail.com> | 229 | Renan Teruo + Paulo Meirelles <renanteruoc@gmail.com> |
191 | Renan Teruo + Rafael Manzo <renanteruoc@gmail.com> | 230 | Renan Teruo + Rafael Manzo <renanteruoc@gmail.com> |
192 | -Rodrigo Souto <diguliu@gmail.com> | 231 | +Rodrigo Souto + Ana Losnak + Daniel Bucher + Caio Almeida + Leandro Nunes + Daniela Feitosa + Mariel Zasso <noosfero-br@listas.softwarelivre.org> |
193 | Rodrigo Souto <rodrigo@colivre.coop.br> | 232 | Rodrigo Souto <rodrigo@colivre.coop.br> |
194 | Ronny Kursawe <kursawe.ronny@googlemail.com> | 233 | Ronny Kursawe <kursawe.ronny@googlemail.com> |
195 | root <root@debian.sdr.serpro> | 234 | root <root@debian.sdr.serpro> |
196 | Samuel R. C. Vale <srcvale@holoscopio.com> | 235 | Samuel R. C. Vale <srcvale@holoscopio.com> |
236 | +Tallys Martins <tallysmartins@gmail.com> | ||
237 | +tallys <tallys@tallys.(none)> | ||
238 | +Thiago Zoroastro <thiago.zoroastro@bol.com.br> | ||
239 | +Valessio Brito <contato@valessiobrito.com.br> | ||
240 | +Valessio Brito <contato@valessiobrito.info> | ||
197 | Valessio Brito <valessio@gmail.com> | 241 | Valessio Brito <valessio@gmail.com> |
198 | vfcosta <vfcosta@gmail.com> | 242 | vfcosta <vfcosta@gmail.com> |
243 | +Victor Carvalho <victorhugodf.ac@gmail.com> | ||
199 | Victor Costa <vfcosta@gmail.com> | 244 | Victor Costa <vfcosta@gmail.com> |
245 | +Victor Hugo Alves de Carvalho <victorhugodf.ac@gmail.com> | ||
200 | Vinicius Cubas Brand <viniciuscb@gmail.com> | 246 | Vinicius Cubas Brand <viniciuscb@gmail.com> |
201 | Visita <visita@debian.(none)> | 247 | Visita <visita@debian.(none)> |
202 | Yann Lugrin <yann.lugrin@liquid-concept.ch> | 248 | Yann Lugrin <yann.lugrin@liquid-concept.ch> |
@@ -0,0 +1,124 @@ | @@ -0,0 +1,124 @@ | ||
1 | +# Noosfero Development Policy | ||
2 | + | ||
3 | +## Developer Roles | ||
4 | + | ||
5 | +* *Developers* are everyone that is contributing code to Noosfero. | ||
6 | +* *Committers* are the people with direct commit access to the Noosfero source | ||
7 | + code. They are responsible for reviewing contributions from other developers | ||
8 | + and integrating them in the Noosfero code base. They are the members of the | ||
9 | + [Noosfero group on Gitlab](https://gitlab.com/groups/noosfero/members). | ||
10 | +* *Release managers* are the people that are managing the release of a new | ||
11 | + Noosfero version and/or the maintainance work of an existing Noosfero stable | ||
12 | + branch. See MAINTAINANCE.md for details on the maintaince policy. | ||
13 | + | ||
14 | +## Development process | ||
15 | + | ||
16 | +* Every new feature or non-trivial bugfix should be reviewed by at least one | ||
17 | + committer. This must be the case even if the original author is a committer. | ||
18 | + | ||
19 | + * In the case the original author is a committer, he/she should feel free to | ||
20 | + commit directly if after 1 week nobody has provided any kind of feedback. | ||
21 | + | ||
22 | + * Developers who are not committers should feel free to ping committers if | ||
23 | + they do not get feedback on their contributions after 1 week. | ||
24 | + | ||
25 | + * On GitLab, one can just add a comment to the merge request; one can also | ||
26 | + @-mention specific committers or other developers who have expertise on | ||
27 | + the area of the contribution. | ||
28 | + | ||
29 | + * Committers should follow the activity of the project, and try to help | ||
30 | + reviewing contributions from others as much as possible. | ||
31 | + | ||
32 | + * On GitLab one can get emails for all activity on a project by setting the | ||
33 | + [notification settings](https://gitlab.com/profile/notifications) to | ||
34 | + "watch". | ||
35 | + | ||
36 | + * Anyone can help by reviewing contributions. Committers are the only ones | ||
37 | + who can give the final approval to a contribution, but everyone is welcome | ||
38 | + to help with code review, testing, etc. | ||
39 | + | ||
40 | + * See note above about setting up notification on GitLab. | ||
41 | + | ||
42 | +* Committers should feel free to push trivial (or urgent) changes directly. | ||
43 | + There are no strict rule on what makes a change trivial or urgent; committers | ||
44 | + are expected to exercise good judgement on a case by case basis. | ||
45 | + | ||
46 | + * Usually changes to the database are not trivial. | ||
47 | + | ||
48 | +* In the case of unsolvable conflict between commiters regarding any change to | ||
49 | + the code, the current release manager(s) will have the final say in the | ||
50 | + matter. | ||
51 | + | ||
52 | +* Release managers are responsible for stablishing a release schedule, and | ||
53 | + about deciding when and what to release. | ||
54 | + | ||
55 | + * Release managers should announce release schedules to the project mailing | ||
56 | + lists in advance. | ||
57 | + | ||
58 | + * The release schedule may include a period of feature freeze, during which | ||
59 | + no new features or any other changes that are not pre-approved by the | ||
60 | + release manager must be committed to the repository. | ||
61 | + | ||
62 | + * Committers must respect the release schedule and feature freezes. | ||
63 | + | ||
64 | +## Maintainance process | ||
65 | + | ||
66 | +### Not all feature releases will be maintained as a stable release | ||
67 | + | ||
68 | +We will be choosing specific release series to be maintained as stable | ||
69 | +releases. | ||
70 | + | ||
71 | +This means that a given release is not guaranteed to be maintained as a stable | ||
72 | +release, but does *not* mean it won't be. Any committer (or anyone, really) can | ||
73 | +decide to maintain a given release as stable and seek help from others to do | ||
74 | +so. | ||
75 | + | ||
76 | +### No merges from stable branches to master | ||
77 | + | ||
78 | +*All* changes must be submitted against the master branch first, and when | ||
79 | +applicable, backported to the desired stable releases. Exceptions to this rules | ||
80 | +are bug fixes that only apply to a given stable branch and not to master. | ||
81 | + | ||
82 | +In the past we had non-trivial changes accepted into stable releases while | ||
83 | +master was way ahead (e.g. during the rails3 migration period), that made the | ||
84 | +merge back into master very painful. By eliminating the need to do these | ||
85 | +merges, we save time for the people responsible for the release, and eliminate | ||
86 | +the possibility of human errors or oversights causing changes to be accepted | ||
87 | +into stable that will be a problem to merge back into master. | ||
88 | + | ||
89 | +By getting all fixes in master first, we improve the chances that a future | ||
90 | +release will not present regressions against bugs that should already be fixed, | ||
91 | +but the fixes got lost in a big, complicated merge (and those won't exist | ||
92 | +anymore, at least not from stable branches to master). | ||
93 | + | ||
94 | +After a fix gets into master, backporting changes into a stable release branch | ||
95 | +is the responsibility of whoever is maintaing that branch, and those interested | ||
96 | +in it. The stable branch release manager(s) are entitled the final say on any | ||
97 | +matters related to that branch. | ||
98 | + | ||
99 | +## Apendix A: how to become a committer | ||
100 | + | ||
101 | +Every developer that wants to be a committer should create [an issue on | ||
102 | +Gitlab](https://gitlab.com/noosfero/noosfero/issues) requesting to be added as | ||
103 | +a committer. This request must include information about the requestor's | ||
104 | +previous contributions to the project. | ||
105 | + | ||
106 | +If 2 or more commiters consider second the request, the requestor is accepted | ||
107 | +as new commiter and added to the Noosfero group. | ||
108 | + | ||
109 | +The existing committers are free to choose whatever criteria they want to | ||
110 | +second the request, but they must be sure that the new committer is a | ||
111 | +responsible developer and knows what she/he is doing. They must be aware that | ||
112 | +seconding these requests means seconding the actions of the new committer: if | ||
113 | +the new committer screw up, her/his seconds screwed up. | ||
114 | + | ||
115 | +## Apendix B: how to become a release manager | ||
116 | + | ||
117 | +A new release manager for the development version of Noosfero (i.e. the one | ||
118 | +that includes new features, a.k.a. the master branch) is apointed by the | ||
119 | +current release manager, and must be a committer first. | ||
120 | + | ||
121 | +Release managers for stable branches are self-appointed, i.e. whoever takes the | ||
122 | +work takes the role. In case of a conflict (e.g. 2+ different people want to do | ||
123 | +the work but can't agree on working together), the development release manager | ||
124 | +decides. |
Gemfile
1 | source "https://rubygems.org" | 1 | source "https://rubygems.org" |
2 | -gem 'rails' | ||
3 | -gem 'fast_gettext' | ||
4 | -gem 'acts-as-taggable-on' | ||
5 | -gem 'prototype-rails' | ||
6 | -gem 'prototype_legacy_helper', '0.0.0', :path => 'vendor/prototype_legacy_helper' | ||
7 | -gem 'rails_autolink' | ||
8 | -gem 'pg' | ||
9 | -gem 'rmagick' | ||
10 | -gem 'RedCloth' | ||
11 | -gem 'will_paginate' | ||
12 | -gem 'ruby-feedparser' | ||
13 | -gem 'daemons' | ||
14 | -gem 'thin' | ||
15 | -gem 'hpricot' | ||
16 | -gem 'nokogiri' | 2 | +gem 'rails', '~> 3.2.19' |
3 | +gem 'fast_gettext', '~> 0.6.8' | ||
4 | +gem 'acts-as-taggable-on', '~> 3.0.2' | ||
5 | +gem 'prototype-rails', '~> 3.2.1' | ||
6 | +gem 'prototype_legacy_helper', '0.0.0', :path => 'vendor/prototype_legacy_helper' | ||
7 | +gem 'rails_autolink', '~> 1.1.5' | ||
8 | +gem 'pg', '~> 0.13.2' | ||
9 | +gem 'rmagick', '~> 2.13.1' | ||
10 | +gem 'RedCloth', '~> 4.2.9' | ||
11 | +gem 'will_paginate', '~> 3.0.3' | ||
12 | +gem 'ruby-feedparser', '~> 0.7' | ||
13 | +gem 'daemons', '~> 1.1.5' | ||
14 | +gem 'thin', '~> 1.3.1' | ||
15 | +gem 'hpricot', '~> 0.8.6' | ||
16 | +gem 'nokogiri', '~> 1.5.5' | ||
17 | gem 'rake', :require => false | 17 | gem 'rake', :require => false |
18 | -gem 'rest-client' | 18 | +gem 'rest-client', '~> 1.6.7' |
19 | +gem 'exception_notification', '~> 4.0.1' | ||
20 | +gem 'gettext', '~> 2.2.1', :require => false, :group => :development | ||
21 | +gem 'locale', '~> 2.0.5' | ||
19 | 22 | ||
20 | # FIXME list here all actual dependencies (i.e. the ones in debian/control), | 23 | # FIXME list here all actual dependencies (i.e. the ones in debian/control), |
21 | # with their GEM names (not the Debian package names) | 24 | # with their GEM names (not the Debian package names) |
22 | 25 | ||
23 | group :production do | 26 | group :production do |
24 | - gem 'dalli' | 27 | + gem 'dalli', '~> 2.7.0' |
25 | end | 28 | end |
26 | 29 | ||
27 | group :test do | 30 | group :test do |
28 | - gem 'rspec' | ||
29 | - gem 'rspec-rails' | ||
30 | - gem 'mocha', :require => false | 31 | + gem 'rspec', '~> 2.10.0' |
32 | + gem 'rspec-rails', '~> 2.10.1' | ||
33 | + gem 'mocha', '~> 1.1.0', :require => false | ||
31 | end | 34 | end |
32 | 35 | ||
33 | group :cucumber do | 36 | group :cucumber do |
34 | - gem 'rake' | ||
35 | - gem 'cucumber-rails', :require => false | ||
36 | - gem 'capybara' | ||
37 | - gem 'cucumber' | ||
38 | - gem 'database_cleaner' | ||
39 | - gem 'selenium-webdriver' | 37 | + gem 'cucumber-rails', '~> 1.0.6', :require => false |
38 | + gem 'capybara', '~> 2.1.0' | ||
39 | + gem 'cucumber', '~> 1.0.6' | ||
40 | + gem 'database_cleaner', '~> 1.2.0' | ||
41 | + gem 'selenium-webdriver', '~> 2.39.0' | ||
40 | end | 42 | end |
41 | 43 | ||
42 | -# include plugin gemfiles | ||
43 | -Dir.glob(File.join('config', 'plugins', '*')).each do |plugin| | ||
44 | - plugin_gemfile = File.join(plugin, 'Gemfile') | ||
45 | - eval File.read(plugin_gemfile) if File.exists?(plugin_gemfile) | 44 | +# include gemfiles from enabled plugins |
45 | +# plugins in baseplugins/ are not included on purpose. They should not have any | ||
46 | +# dependencies. | ||
47 | +Dir.glob('config/plugins/*/Gemfile').each do |gemfile| | ||
48 | + eval File.read(gemfile) | ||
46 | end | 49 | end |
Gemfile.lock
@@ -1,187 +0,0 @@ | @@ -1,187 +0,0 @@ | ||
1 | -PATH | ||
2 | - remote: vendor/prototype_legacy_helper | ||
3 | - specs: | ||
4 | - prototype_legacy_helper (0.0.0) | ||
5 | - | ||
6 | -GEM | ||
7 | - remote: https://rubygems.org/ | ||
8 | - specs: | ||
9 | - RedCloth (4.2.9) | ||
10 | - actionmailer (3.2.6) | ||
11 | - actionpack (= 3.2.6) | ||
12 | - mail (~> 2.4.4) | ||
13 | - actionpack (3.2.6) | ||
14 | - activemodel (= 3.2.6) | ||
15 | - activesupport (= 3.2.6) | ||
16 | - builder (~> 3.0.0) | ||
17 | - erubis (~> 2.7.0) | ||
18 | - journey (~> 1.0.1) | ||
19 | - rack (~> 1.4.0) | ||
20 | - rack-cache (~> 1.2) | ||
21 | - rack-test (~> 0.6.1) | ||
22 | - sprockets (~> 2.1.3) | ||
23 | - activemodel (3.2.6) | ||
24 | - activesupport (= 3.2.6) | ||
25 | - builder (~> 3.0.0) | ||
26 | - activerecord (3.2.6) | ||
27 | - activemodel (= 3.2.6) | ||
28 | - activesupport (= 3.2.6) | ||
29 | - arel (~> 3.0.2) | ||
30 | - tzinfo (~> 0.3.29) | ||
31 | - activeresource (3.2.6) | ||
32 | - activemodel (= 3.2.6) | ||
33 | - activesupport (= 3.2.6) | ||
34 | - activesupport (3.2.6) | ||
35 | - i18n (~> 0.6) | ||
36 | - multi_json (~> 1.0) | ||
37 | - acts-as-taggable-on (3.0.2) | ||
38 | - rails (>= 3, < 5) | ||
39 | - arel (3.0.2) | ||
40 | - builder (3.0.0) | ||
41 | - capybara (2.1.0) | ||
42 | - mime-types (>= 1.16) | ||
43 | - nokogiri (>= 1.3.3) | ||
44 | - rack (>= 1.0.0) | ||
45 | - rack-test (>= 0.5.4) | ||
46 | - xpath (~> 2.0) | ||
47 | - childprocess (0.3.3) | ||
48 | - ffi (~> 1.0.6) | ||
49 | - cucumber (1.0.6) | ||
50 | - builder (>= 2.1.2) | ||
51 | - diff-lcs (>= 1.1.2) | ||
52 | - gherkin (~> 2.4.18) | ||
53 | - json (>= 1.4.6) | ||
54 | - term-ansicolor (>= 1.0.6) | ||
55 | - cucumber-rails (1.0.6) | ||
56 | - capybara (>= 1.1.1) | ||
57 | - cucumber (>= 1.0.6) | ||
58 | - nokogiri (>= 1.5.0) | ||
59 | - daemons (1.1.5) | ||
60 | - dalli (2.7.0) | ||
61 | - database_cleaner (1.2.0) | ||
62 | - diff-lcs (1.1.3) | ||
63 | - erubis (2.7.0) | ||
64 | - eventmachine (0.12.11) | ||
65 | - fast_gettext (0.6.8) | ||
66 | - ffi (1.0.11) | ||
67 | - gherkin (2.4.21) | ||
68 | - json (>= 1.4.6) | ||
69 | - hike (1.2.1) | ||
70 | - hpricot (0.8.6) | ||
71 | - i18n (0.6.0) | ||
72 | - journey (1.0.3) | ||
73 | - json (1.7.3) | ||
74 | - mail (2.4.4) | ||
75 | - i18n (>= 0.4.0) | ||
76 | - mime-types (~> 1.16) | ||
77 | - treetop (~> 1.4.8) | ||
78 | - metaclass (0.0.1) | ||
79 | - mime-types (1.19) | ||
80 | - mocha (0.11.3) | ||
81 | - metaclass (~> 0.0.1) | ||
82 | - multi_json (1.3.6) | ||
83 | - nokogiri (1.5.5) | ||
84 | - pg (0.13.2) | ||
85 | - polyglot (0.3.3) | ||
86 | - prototype-rails (3.2.1) | ||
87 | - rails (~> 3.2) | ||
88 | - rack (1.4.1) | ||
89 | - rack-cache (1.2) | ||
90 | - rack (>= 0.4) | ||
91 | - rack-ssl (1.3.2) | ||
92 | - rack | ||
93 | - rack-test (0.6.1) | ||
94 | - rack (>= 1.0) | ||
95 | - rails (3.2.6) | ||
96 | - actionmailer (= 3.2.6) | ||
97 | - actionpack (= 3.2.6) | ||
98 | - activerecord (= 3.2.6) | ||
99 | - activeresource (= 3.2.6) | ||
100 | - activesupport (= 3.2.6) | ||
101 | - bundler (~> 1.0) | ||
102 | - railties (= 3.2.6) | ||
103 | - rails_autolink (1.1.5) | ||
104 | - rails (> 3.1) | ||
105 | - railties (3.2.6) | ||
106 | - actionpack (= 3.2.6) | ||
107 | - activesupport (= 3.2.6) | ||
108 | - rack-ssl (~> 1.3.2) | ||
109 | - rake (>= 0.8.7) | ||
110 | - rdoc (~> 3.4) | ||
111 | - thor (>= 0.14.6, < 2.0) | ||
112 | - rake (0.9.2.2) | ||
113 | - rdoc (3.9.4) | ||
114 | - rest-client (1.6.7) | ||
115 | - mime-types (>= 1.16) | ||
116 | - rmagick (2.13.1) | ||
117 | - rspec (2.10.0) | ||
118 | - rspec-core (~> 2.10.0) | ||
119 | - rspec-expectations (~> 2.10.0) | ||
120 | - rspec-mocks (~> 2.10.0) | ||
121 | - rspec-core (2.10.1) | ||
122 | - rspec-expectations (2.10.0) | ||
123 | - diff-lcs (~> 1.1.3) | ||
124 | - rspec-mocks (2.10.1) | ||
125 | - rspec-rails (2.10.1) | ||
126 | - actionpack (>= 3.0) | ||
127 | - activesupport (>= 3.0) | ||
128 | - railties (>= 3.0) | ||
129 | - rspec (~> 2.10.0) | ||
130 | - ruby-feedparser (0.7) | ||
131 | - rubyzip (1.1.2) | ||
132 | - selenium-webdriver (2.39.0) | ||
133 | - childprocess (>= 0.2.5) | ||
134 | - multi_json (~> 1.0) | ||
135 | - rubyzip (~> 1.0) | ||
136 | - websocket (~> 1.0.4) | ||
137 | - sprockets (2.1.3) | ||
138 | - hike (~> 1.2) | ||
139 | - multi_json (~> 1.0) | ||
140 | - rack (~> 1.0) | ||
141 | - tilt (~> 1.1, != 1.3.0) | ||
142 | - term-ansicolor (1.0.7) | ||
143 | - thin (1.3.1) | ||
144 | - daemons (>= 1.0.9) | ||
145 | - eventmachine (>= 0.12.6) | ||
146 | - rack (>= 1.0.0) | ||
147 | - thor (0.15.3) | ||
148 | - tilt (1.3.3) | ||
149 | - treetop (1.4.10) | ||
150 | - polyglot | ||
151 | - polyglot (>= 0.3.1) | ||
152 | - tzinfo (0.3.33) | ||
153 | - websocket (1.0.7) | ||
154 | - will_paginate (3.0.3) | ||
155 | - xpath (2.0.0) | ||
156 | - nokogiri (~> 1.3) | ||
157 | - | ||
158 | -PLATFORMS | ||
159 | - ruby | ||
160 | - | ||
161 | -DEPENDENCIES | ||
162 | - RedCloth | ||
163 | - acts-as-taggable-on | ||
164 | - capybara | ||
165 | - cucumber | ||
166 | - cucumber-rails | ||
167 | - daemons | ||
168 | - dalli | ||
169 | - database_cleaner | ||
170 | - fast_gettext | ||
171 | - hpricot | ||
172 | - mocha | ||
173 | - nokogiri | ||
174 | - pg | ||
175 | - prototype-rails | ||
176 | - prototype_legacy_helper (= 0.0.0)! | ||
177 | - rails | ||
178 | - rails_autolink | ||
179 | - rake | ||
180 | - rest-client | ||
181 | - rmagick | ||
182 | - rspec | ||
183 | - rspec-rails | ||
184 | - ruby-feedparser | ||
185 | - selenium-webdriver | ||
186 | - thin | ||
187 | - will_paginate |
INSTALL.https.md
1 | -Setup Noosfero to use HTTPS | ||
2 | -=========================== | 1 | +# Setup Noosfero to use HTTPS |
3 | 2 | ||
4 | This document assumes that you have a fully and clean Noosfero | 3 | This document assumes that you have a fully and clean Noosfero |
5 | installation as explained at the `INSTALL.md` file. | 4 | installation as explained at the `INSTALL.md` file. |
6 | 5 | ||
7 | -SSL certificate | ||
8 | -+++++++++++++++ | 6 | +## Creating a self-signed SSL certificate |
9 | 7 | ||
10 | You should get a valid SSL certificate, but if you want to test | 8 | You should get a valid SSL certificate, but if you want to test |
11 | your setup before, you could generate a self-signed certificate | 9 | your setup before, you could generate a self-signed certificate |
@@ -17,99 +15,106 @@ as below: | @@ -17,99 +15,106 @@ as below: | ||
17 | # openssl req -new -x509 -nodes -sha1 -days $[10*365] -key noosfero.key > noosfero.cert | 15 | # openssl req -new -x509 -nodes -sha1 -days $[10*365] -key noosfero.key > noosfero.cert |
18 | # cat noosfero.key noosfero.cert > noosfero.pem | 16 | # cat noosfero.key noosfero.cert > noosfero.pem |
19 | 17 | ||
18 | +## Web server configuration | ||
19 | + | ||
20 | There are two ways of using SSL with Noosfero: 1) If you are not using | 20 | There are two ways of using SSL with Noosfero: 1) If you are not using |
21 | Varnish; and 2) If you are using Varnish. | 21 | Varnish; and 2) If you are using Varnish. |
22 | 22 | ||
23 | -1) If you are are not using Varnish | ||
24 | -+++++++++++++++++++++++++++++++++++ | 23 | +### 1) If you are are not using Varnish |
25 | 24 | ||
26 | Simply do a redirect in apache to force all connections with SSL: | 25 | Simply do a redirect in apache to force all connections with SSL: |
27 | 26 | ||
28 | - <VirtualHost *:8080> | ||
29 | - ServerName test.stoa.usp.br | ||
30 | - | ||
31 | - Redirect / https://example.com/ | ||
32 | - </VirtualHost> | 27 | +``` |
28 | +<VirtualHost *:8080> | ||
29 | + ServerName test.stoa.usp.br | ||
30 | + Redirect / https://example.com/ | ||
31 | +</VirtualHost> | ||
32 | +``` | ||
33 | 33 | ||
34 | And set a vhost to receive then: | 34 | And set a vhost to receive then: |
35 | 35 | ||
36 | - <VirtualHost *:443> | ||
37 | - ServerName example.com | ||
38 | - | ||
39 | - SSLEngine On | ||
40 | - SSLCertificateFile /etc/ssl/certs/cert.pem | ||
41 | - SSLCertificateKeyFile /etc/ssl/private/cert.key | ||
42 | - | ||
43 | - Include /etc/noosfero/apache/virtualhost.conf | ||
44 | - </VirtualHost> | 36 | +``` |
37 | +<VirtualHost *:443> | ||
38 | + ServerName example.com | ||
39 | + SSLEngine On | ||
40 | + SSLCertificateFile /etc/ssl/certs/cert.pem | ||
41 | + SSLCertificateKeyFile /etc/ssl/private/cert.key | ||
42 | + Include /etc/noosfero/apache/virtualhost.conf | ||
43 | +</VirtualHost> | ||
44 | +``` | ||
45 | 45 | ||
46 | Be aware that if you had configured varnish, the requests won't reach | 46 | Be aware that if you had configured varnish, the requests won't reach |
47 | it with this configuration. | 47 | it with this configuration. |
48 | 48 | ||
49 | -2) If you are using Varnish | ||
50 | -+++++++++++++++++++++++++++ | ||
51 | - | ||
52 | -Varnish isn't able to communicate with the SSL protocol, so we will | ||
53 | -need some one who do this and Pound[1] can do the job. In order to | ||
54 | -install it in Debian based systems: | 49 | +### 2) If you are using Varnish |
55 | 50 | ||
56 | - $ sudo apt-get install pound | 51 | +Varnish isn't able to communicate with the SSL protocol, so we will need some |
52 | +one else who do this and [Pound](http://www.apsis.ch/pound) can do the job. In | ||
53 | +order to install it in Debian based systems: | ||
57 | 54 | ||
58 | -Set Varnish to listen in other port than 80: | 55 | +``` |
56 | +$ sudo apt-get install pound | ||
57 | +``` | ||
59 | 58 | ||
60 | -/etc/defaults/varnish | ||
61 | ---------------------- | 59 | +Set Varnish to listen in other port than 80 in `/etc/defaults/varnish`: |
62 | 60 | ||
63 | - DAEMON_OPTS="-a localhost:6081 \ | ||
64 | - -T localhost:6082 \ | ||
65 | - -f /etc/varnish/default.vcl \ | ||
66 | - -S /etc/varnish/secret \ | ||
67 | - -s file,/var/lib/varnish/$INSTANCE/varnish_storage.bin,1G" | 61 | +``` |
62 | +DAEMON_OPTS="-a localhost:6081 \ | ||
63 | + -T localhost:6082 \ | ||
64 | + -f /etc/varnish/default.vcl \ | ||
65 | + -S /etc/varnish/secret \ | ||
66 | + -s file,/var/lib/varnish/$INSTANCE/varnish_storage.bin,1G" | ||
67 | +``` | ||
68 | 68 | ||
69 | Configure Pound: | 69 | Configure Pound: |
70 | 70 | ||
71 | - # cp /usr/share/noosfero/etc/pound.cfg /etc/pound/ | ||
72 | - | ||
73 | -Edit /etc/pound.cfg and set the IP and domain of your server. | 71 | +``` |
72 | +# cp /usr/share/noosfero/etc/pound.cfg /etc/pound/ | ||
73 | +``` | ||
74 | 74 | ||
75 | -Configure Pound to start at system initialization: | 75 | +Edit `/etc/pound.cfg` and set the IP and domain of your server. |
76 | 76 | ||
77 | -/etc/default/pound | 77 | +Configure Pound to start at system initialization. At `/etc/default/pound`: |
78 | ------------------ | 78 | ------------------ |
79 | 79 | ||
80 | - startup=1 | 80 | +``` |
81 | +startup=1 | ||
82 | +``` | ||
81 | 83 | ||
82 | -Set Apache to only listen to localhost: | 84 | +Set Apache to only listen to localhost, at `/etc/apache2/ports.conf`: |
83 | 85 | ||
84 | -/etc/apache2/ports.conf | ||
85 | ------------------------ | ||
86 | - | ||
87 | - Listen 127.0.0.1:8080 | 86 | +``` |
87 | +Listen 127.0.0.1:8080 | ||
88 | +``` | ||
88 | 89 | ||
89 | Restart the services: | 90 | Restart the services: |
90 | 91 | ||
91 | - $ sudo service apache2 restart | ||
92 | - $ sudo service varnish restart | 92 | +``` |
93 | +$ sudo service apache2 restart | ||
94 | +$ sudo service varnish restart | ||
95 | +``` | ||
93 | 96 | ||
94 | Start pound: | 97 | Start pound: |
95 | 98 | ||
96 | - $ sudo service pound start | ||
97 | - | ||
98 | -[1] http://www.apsis.ch/pound | 99 | +``` |
100 | +$ sudo service pound start | ||
101 | +``` | ||
99 | 102 | ||
100 | -Noosfero XMPP chat | ||
101 | -++++++++++++++++++ | 103 | +## Noosfero XMPP chat |
102 | 104 | ||
103 | If you want to use chat over HTTPS, then you should add the domain | 105 | If you want to use chat over HTTPS, then you should add the domain |
104 | -and IP of your server in the /etc/hosts file, example: | 106 | +and IP of your server in the /etc/hosts file, example |
105 | 107 | ||
106 | -/etc/hosts | ||
107 | ----------- | 108 | +`/etc/hosts:` |
108 | 109 | ||
109 | - 192.168.1.86 mydomain.example.com | 110 | +``` |
111 | +192.168.1.86 mydomain.example.com | ||
112 | +``` | ||
110 | 113 | ||
111 | -Also, it's recomended that you remove lines above from the file | 114 | +Also, it's recomended that you remove the lines below from the file |
112 | `/etc/apache2/sites-enabled/noosfero`: | 115 | `/etc/apache2/sites-enabled/noosfero`: |
113 | 116 | ||
114 | - RewriteEngine On | ||
115 | - Include /usr/share/noosfero/util/chat/apache/xmpp.conf | 117 | +``` |
118 | +RewriteEngine On | ||
119 | +Include /usr/share/noosfero/util/chat/apache/xmpp.conf | ||
120 | +``` |
@@ -0,0 +1,29 @@ | @@ -0,0 +1,29 @@ | ||
1 | +Using custom locales | ||
2 | +==================== | ||
3 | + | ||
4 | +Personalized translations go into the `config/custom_locales/` directory. | ||
5 | +Custom locales can be identified by the rails environment, schema name in a | ||
6 | +multitenancy setup or domain name until the first dot (e.g env1.coop.br for the | ||
7 | +example below). | ||
8 | + | ||
9 | +Currently, the only filename prefix for the localization file which is | ||
10 | +processed is "environment". For instance, a POT file would be called | ||
11 | +"environment.pot". | ||
12 | + | ||
13 | +The structure of an environment named env1 with custom translations for both | ||
14 | +Portuguese and Spanish and an environment named env2 with custom Russian | ||
15 | +translation would be: | ||
16 | + | ||
17 | + config/ | ||
18 | + custom_locales/ | ||
19 | + env1/ | ||
20 | + environment.pot | ||
21 | + pt/ | ||
22 | + environment.po | ||
23 | + es/ | ||
24 | + environment.po | ||
25 | + env2/ | ||
26 | + environment.pot | ||
27 | + ru/ | ||
28 | + environment.po | ||
29 | + |
INSTALL.md
@@ -186,8 +186,8 @@ Apache instalation | @@ -186,8 +186,8 @@ Apache instalation | ||
186 | 186 | ||
187 | # apt-get install apache2 | 187 | # apt-get install apache2 |
188 | 188 | ||
189 | -Apache configuration | ||
190 | --------------------- | 189 | +Configuration - noosfero at / |
190 | +----------------------------- | ||
191 | 191 | ||
192 | First you have to enable the following some apache modules: | 192 | First you have to enable the following some apache modules: |
193 | 193 | ||
@@ -257,6 +257,62 @@ Now restart your apache server (as root): | @@ -257,6 +257,62 @@ Now restart your apache server (as root): | ||
257 | 257 | ||
258 | # invoke-rc.d apache2 restart | 258 | # invoke-rc.d apache2 restart |
259 | 259 | ||
260 | +Configuration - noosfero at a /subdirectory | ||
261 | +------------------------------------------- | ||
262 | + | ||
263 | +This section describes how to configure noosfero at a subdirectory, what is | ||
264 | +specially useful when you want Noosfero to share a domain name with other | ||
265 | +applications. For example you can host noosfero at yourdomain.com/social, a | ||
266 | +webmail application at yourdomain.com/webmail, and have a static HTML website | ||
267 | +at yourdomain.com/. | ||
268 | + | ||
269 | +**NOTE:** Some plugins might not work well with this setting. Before deploying | ||
270 | +this setting, make sure you test that everything you need works properly with | ||
271 | +it. | ||
272 | + | ||
273 | +The configuration is similar to the main configuration instructions, except for | ||
274 | +the following points. In the description below, replace '/subdirectory' with | ||
275 | +the actual subdirectory you want. | ||
276 | + | ||
277 | +1) add a `prefix: /subdirectory` line to your thin configuration file (thin.yml). | ||
278 | + | ||
279 | +1.1) remember to restart the noosfero application server whenever you make | ||
280 | +changes to that configuration file. | ||
281 | + | ||
282 | + # service noosfero restart | ||
283 | + | ||
284 | +2) add a line saying `export RAILS_RELATIVE_URL_ROOT=/subdirectory` to | ||
285 | +/etc/default/noosfero (you can create it with just this line if it does not | ||
286 | +exist already). | ||
287 | + | ||
288 | +3) You should add the following apache configuration to an existing virtual | ||
289 | +host (plus the `<Proxy balancer://noosfero>` section as displayed above): | ||
290 | + | ||
291 | +``` | ||
292 | +Alias /subdirectory /path/to/noosfero/public | ||
293 | +<Directory "/path/to/noosfero/public"> | ||
294 | + Options FollowSymLinks | ||
295 | + AllowOverride None | ||
296 | + Order Allow,Deny | ||
297 | + Allow from all | ||
298 | + | ||
299 | + Include /path/to/noosfero/etc/noosfero/apache/cache.conf | ||
300 | + | ||
301 | + RewriteEngine On | ||
302 | + RewriteBase /subdirectory | ||
303 | + # Rewrite index to check for static index.html | ||
304 | + RewriteRule ^$ index.html [QSA] | ||
305 | + # Rewrite to check for Rails cached page | ||
306 | + RewriteRule ^([^.]+)$ $1.html [QSA] | ||
307 | + RewriteCond %{REQUEST_FILENAME} !-f | ||
308 | + RewriteRule ^(.*)$ http://localhost:3000%{REQUEST_URI} [P,QSA,L] | ||
309 | +</Directory> | ||
310 | +``` | ||
311 | + | ||
312 | +3.1) remember to reload the apache server whenever any apache configuration | ||
313 | +file changes. | ||
314 | + | ||
315 | + # sudo service apache2 reload | ||
260 | 316 | ||
261 | Enabling exception notifications | 317 | Enabling exception notifications |
262 | ================================ | 318 | ================================ |
Rakefile
1 | #!/usr/bin/env rake | 1 | #!/usr/bin/env rake |
2 | + | ||
2 | # Add your own tasks in files placed in lib/tasks ending in .rake, | 3 | # Add your own tasks in files placed in lib/tasks ending in .rake, |
3 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. | 4 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. |
4 | 5 | ||
5 | require File.expand_path('../config/application', __FILE__) | 6 | require File.expand_path('../config/application', __FILE__) |
6 | 7 | ||
7 | Noosfero::Application.load_tasks | 8 | Noosfero::Application.load_tasks |
9 | + | ||
10 | +[ | ||
11 | + "baseplugins/*/{tasks,lib/tasks,rails/tasks}/**/*.rake", | ||
12 | + "config/plugins/*/{tasks,lib/tasks,rails/tasks}/**/*.rake", | ||
13 | + "config/plugins/*/vendor/plugins/*/{tasks,lib/tasks,rails/tasks}/**/*.rake", | ||
14 | +].map do |pattern| | ||
15 | + Dir.glob(pattern).sort | ||
16 | +end.flatten.each do |taskfile| | ||
17 | + load taskfile | ||
18 | +end |
Vagrantfile
@@ -3,7 +3,7 @@ | @@ -3,7 +3,7 @@ | ||
3 | 3 | ||
4 | VAGRANTFILE_API_VERSION = "2" | 4 | VAGRANTFILE_API_VERSION = "2" |
5 | Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| | 5 | Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| |
6 | - config.vm.box = "debian-wheezy" | 6 | + config.vm.box = ENV.fetch('VAGRANT_BOX', "debian-wheezy") |
7 | config.vm.network :forwarded_port, host: 3000, guest: 3000 | 7 | config.vm.network :forwarded_port, host: 3000, guest: 3000 |
8 | config.vm.provision :shell do |shell| | 8 | config.vm.provision :shell do |shell| |
9 | shell.inline = 'su vagrant -c /vagrant/script/vagrant' | 9 | shell.inline = 'su vagrant -c /vagrant/script/vagrant' |
app/controllers/admin/admin_panel_controller.rb
@@ -71,4 +71,22 @@ class AdminPanelController < AdminController | @@ -71,4 +71,22 @@ class AdminPanelController < AdminController | ||
71 | end | 71 | end |
72 | end | 72 | end |
73 | end | 73 | end |
74 | + | ||
75 | + def manage_organizations_status | ||
76 | + scope = environment.organizations | ||
77 | + @filter = params[:filter] || 'any' | ||
78 | + @title = "Organization profiles" | ||
79 | + @title = @title+" - "+@filter if @filter != 'any' | ||
80 | + | ||
81 | + if @filter == 'enabled' | ||
82 | + scope = scope.visible | ||
83 | + elsif @filter == 'disabled' | ||
84 | + scope = scope.disabled | ||
85 | + end | ||
86 | + | ||
87 | + scope = scope.order('name ASC') | ||
88 | + | ||
89 | + @q = params[:q] | ||
90 | + @collection = find_by_contents(:organizations, scope, @q, {:per_page => 10, :page => params[:npage]})[:results] | ||
91 | + end | ||
74 | end | 92 | end |
app/controllers/admin/categories_controller.rb
@@ -45,9 +45,11 @@ class CategoriesController < AdminController | @@ -45,9 +45,11 @@ class CategoriesController < AdminController | ||
45 | if request.post? | 45 | if request.post? |
46 | @category.update_attributes!(params[:category]) | 46 | @category.update_attributes!(params[:category]) |
47 | @saved = true | 47 | @saved = true |
48 | + session[:notice] = _("Category %s saved." % @category.name) | ||
48 | redirect_to :action => 'index' | 49 | redirect_to :action => 'index' |
49 | end | 50 | end |
50 | rescue Exception => e | 51 | rescue Exception => e |
52 | + session[:notice] = _('Could not save category.') | ||
51 | render :action => 'edit' | 53 | render :action => 'edit' |
52 | end | 54 | end |
53 | end | 55 | end |
app/controllers/admin/environment_design_controller.rb
@@ -3,9 +3,7 @@ class EnvironmentDesignController < BoxOrganizerController | @@ -3,9 +3,7 @@ class EnvironmentDesignController < BoxOrganizerController | ||
3 | protect 'edit_environment_design', :environment | 3 | protect 'edit_environment_design', :environment |
4 | 4 | ||
5 | def available_blocks | 5 | def available_blocks |
6 | - # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from | ||
7 | - # the Noosfero core soon, see ActionItem3045 | ||
8 | - @available_blocks ||= [ ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock, FeaturedProductsBlock, CategoriesBlock, RawHTMLBlock, TagsBlock ] | 6 | + @available_blocks ||= [ ArticleBlock, LoginBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock, FeaturedProductsBlock, CategoriesBlock, RawHTMLBlock, TagsBlock ] |
9 | @available_blocks += plugins.dispatch(:extra_blocks, :type => Environment) | 7 | @available_blocks += plugins.dispatch(:extra_blocks, :type => Environment) |
10 | end | 8 | end |
11 | 9 |
app/controllers/admin/features_controller.rb
@@ -51,4 +51,10 @@ class FeaturesController < AdminController | @@ -51,4 +51,10 @@ class FeaturesController < AdminController | ||
51 | redirect_to :action => 'manage_fields' | 51 | redirect_to :action => 'manage_fields' |
52 | end | 52 | end |
53 | 53 | ||
54 | + def search_members | ||
55 | + arg = params[:q].downcase | ||
56 | + result = environment.people.find(:all, :conditions => ['LOWER(name) LIKE ? OR identifier LIKE ?', "%#{arg}%", "%#{arg}%"]) | ||
57 | + render :text => prepare_to_token_input(result).to_json | ||
58 | + end | ||
59 | + | ||
54 | end | 60 | end |
app/controllers/admin/templates_controller.rb
@@ -40,8 +40,67 @@ class TemplatesController < AdminController | @@ -40,8 +40,67 @@ class TemplatesController < AdminController | ||
40 | end | 40 | end |
41 | end | 41 | end |
42 | 42 | ||
43 | + def set_community_as_default | ||
44 | + begin | ||
45 | + community = environment.communities.find(params[:template_id]) | ||
46 | + rescue ActiveRecord::RecordNotFound | ||
47 | + message = _('Community not found. The template could no be changed.') | ||
48 | + community = nil | ||
49 | + end | ||
50 | + | ||
51 | + message = _('%s defined as default') % community.name if set_as_default(community) | ||
52 | + session[:notice] = message | ||
53 | + | ||
54 | + redirect_to :action => 'index' | ||
55 | + end | ||
56 | + | ||
57 | + def set_person_as_default | ||
58 | + begin | ||
59 | + person = environment.people.find(params[:template_id]) | ||
60 | + rescue ActiveRecord::RecordNotFound | ||
61 | + message = _('Person not found. The template could no be changed.') | ||
62 | + person = nil | ||
63 | + end | ||
64 | + | ||
65 | + message = _('%s defined as default') % person.name if set_as_default(person) | ||
66 | + session[:notice] = message | ||
67 | + | ||
68 | + redirect_to :action => 'index' | ||
69 | + end | ||
70 | + | ||
71 | + def set_enterprise_as_default | ||
72 | + begin | ||
73 | + enterprise = environment.enterprises.find(params[:template_id]) | ||
74 | + rescue ActiveRecord::RecordNotFound | ||
75 | + message = _('Enterprise not found. The template could no be changed.') | ||
76 | + enterprise = nil | ||
77 | + end | ||
78 | + | ||
79 | + message = _('%s defined as default') % enterprise.name if set_as_default(enterprise) | ||
80 | + session[:notice] = message | ||
81 | + | ||
82 | + redirect_to :action => 'index' | ||
83 | + end | ||
84 | + | ||
43 | private | 85 | private |
44 | 86 | ||
87 | + def set_as_default(obj) | ||
88 | + return nil if obj.nil? | ||
89 | + case obj.class.name | ||
90 | + when 'Community' then | ||
91 | + environment.community_default_template = obj | ||
92 | + environment.save! | ||
93 | + when 'Person' then | ||
94 | + environment.person_default_template = obj | ||
95 | + environment.save! | ||
96 | + when 'Enterprise' then | ||
97 | + environment.enterprise_default_template = obj | ||
98 | + environment.save! | ||
99 | + else | ||
100 | + nil | ||
101 | + end | ||
102 | + end | ||
103 | + | ||
45 | def create_organization_template(klass) | 104 | def create_organization_template(klass) |
46 | identifier = params[:name].to_slug | 105 | identifier = params[:name].to_slug |
47 | template = klass.new(:name => params[:name], :identifier => identifier, :is_template => true) | 106 | template = klass.new(:name => params[:name], :identifier => identifier, :is_template => true) |
app/controllers/application_controller.rb
@@ -7,6 +7,12 @@ class ApplicationController < ActionController::Base | @@ -7,6 +7,12 @@ class ApplicationController < ActionController::Base | ||
7 | before_filter :detect_stuff_by_domain | 7 | before_filter :detect_stuff_by_domain |
8 | before_filter :init_noosfero_plugins | 8 | before_filter :init_noosfero_plugins |
9 | before_filter :allow_cross_domain_access | 9 | before_filter :allow_cross_domain_access |
10 | + before_filter :login_required, :if => :private_environment? | ||
11 | + before_filter :verify_members_whitelist, :if => [:private_environment?, :user] | ||
12 | + | ||
13 | + def verify_members_whitelist | ||
14 | + render_access_denied unless user.is_admin? || environment.in_whitelist?(user) | ||
15 | + end | ||
10 | 16 | ||
11 | after_filter :set_csrf_cookie | 17 | after_filter :set_csrf_cookie |
12 | 18 | ||
@@ -34,7 +40,7 @@ class ApplicationController < ActionController::Base | @@ -34,7 +40,7 @@ class ApplicationController < ActionController::Base | ||
34 | 40 | ||
35 | theme_layout = theme_option(:layout) | 41 | theme_layout = theme_option(:layout) |
36 | if theme_layout | 42 | if theme_layout |
37 | - theme_view_file('layouts/'+theme_layout) || theme_layout | 43 | + (theme_view_file('layouts/'+theme_layout) || theme_layout).to_s |
38 | else | 44 | else |
39 | 'application' | 45 | 'application' |
40 | end | 46 | end |
@@ -121,6 +127,9 @@ class ApplicationController < ActionController::Base | @@ -121,6 +127,9 @@ class ApplicationController < ActionController::Base | ||
121 | 127 | ||
122 | # TODO: move this logic somewhere else (Domain class?) | 128 | # TODO: move this logic somewhere else (Domain class?) |
123 | def detect_stuff_by_domain | 129 | def detect_stuff_by_domain |
130 | + # Sets text domain based on request host for custom internationalization | ||
131 | + FastGettext.text_domain = Domain.custom_locale(request.host) | ||
132 | + | ||
124 | @domain = Domain.find_by_name(request.host) | 133 | @domain = Domain.find_by_name(request.host) |
125 | if @domain.nil? | 134 | if @domain.nil? |
126 | @environment = Environment.default | 135 | @environment = Environment.default |
@@ -187,4 +196,8 @@ class ApplicationController < ActionController::Base | @@ -187,4 +196,8 @@ class ApplicationController < ActionController::Base | ||
187 | {:results => scope.paginate(paginate_options)} | 196 | {:results => scope.paginate(paginate_options)} |
188 | end | 197 | end |
189 | 198 | ||
199 | + def private_environment? | ||
200 | + @environment.enabled?(:restrict_to_members) | ||
201 | + end | ||
202 | + | ||
190 | end | 203 | end |
app/controllers/my_profile/cms_controller.rb
@@ -4,6 +4,12 @@ class CmsController < MyProfileController | @@ -4,6 +4,12 @@ class CmsController < MyProfileController | ||
4 | 4 | ||
5 | include ArticleHelper | 5 | include ArticleHelper |
6 | 6 | ||
7 | + def search_tags | ||
8 | + arg = params[:term].downcase | ||
9 | + result = ActsAsTaggableOn::Tag.find(:all, :conditions => ['LOWER(name) LIKE ?', "%#{arg}%"]) | ||
10 | + render :text => prepare_to_token_input_by_label(result).to_json, :content_type => 'application/json' | ||
11 | + end | ||
12 | + | ||
7 | def self.protect_if(*args) | 13 | def self.protect_if(*args) |
8 | before_filter(*args) do |c| | 14 | before_filter(*args) do |c| |
9 | user, profile = c.send(:user), c.send(:profile) | 15 | user, profile = c.send(:user), c.send(:profile) |
@@ -143,6 +149,7 @@ class CmsController < MyProfileController | @@ -143,6 +149,7 @@ class CmsController < MyProfileController | ||
143 | end | 149 | end |
144 | 150 | ||
145 | @article.profile = profile | 151 | @article.profile = profile |
152 | + @article.author = user | ||
146 | @article.last_changed_by = user | 153 | @article.last_changed_by = user |
147 | @article.created_by = user | 154 | @article.created_by = user |
148 | 155 | ||
@@ -167,6 +174,8 @@ class CmsController < MyProfileController | @@ -167,6 +174,8 @@ class CmsController < MyProfileController | ||
167 | 174 | ||
168 | post_only :set_home_page | 175 | post_only :set_home_page |
169 | def set_home_page | 176 | def set_home_page |
177 | + return render_access_denied unless user.can_change_homepage? | ||
178 | + | ||
170 | article = params[:id].nil? ? nil : profile.articles.find(params[:id]) | 179 | article = params[:id].nil? ? nil : profile.articles.find(params[:id]) |
171 | profile.update_attribute(:home_page, article) | 180 | profile.update_attribute(:home_page, article) |
172 | 181 | ||
@@ -195,7 +204,7 @@ class CmsController < MyProfileController | @@ -195,7 +204,7 @@ class CmsController < MyProfileController | ||
195 | :profile => profile, | 204 | :profile => profile, |
196 | :parent => @parent, | 205 | :parent => @parent, |
197 | :last_changed_by => user, | 206 | :last_changed_by => user, |
198 | - :created_by => user, | 207 | + :author => user, |
199 | }, | 208 | }, |
200 | :without_protection => true | 209 | :without_protection => true |
201 | ) | 210 | ) |
@@ -205,6 +214,7 @@ class CmsController < MyProfileController | @@ -205,6 +214,7 @@ class CmsController < MyProfileController | ||
205 | if @errors.any? | 214 | if @errors.any? |
206 | render :action => 'upload_files', :parent_id => @parent_id | 215 | render :action => 'upload_files', :parent_id => @parent_id |
207 | else | 216 | else |
217 | + session[:notice] = _('File(s) successfully uploaded') | ||
208 | if @back_to | 218 | if @back_to |
209 | redirect_to @back_to | 219 | redirect_to @back_to |
210 | elsif @parent | 220 | elsif @parent |
@@ -220,7 +230,7 @@ class CmsController < MyProfileController | @@ -220,7 +230,7 @@ class CmsController < MyProfileController | ||
220 | @article = profile.articles.find(params[:id]) | 230 | @article = profile.articles.find(params[:id]) |
221 | if request.post? | 231 | if request.post? |
222 | @article.destroy | 232 | @article.destroy |
223 | - session[:notice] = _("\"#{@article.name}\" was removed.") | 233 | + session[:notice] = _("\"%s\" was removed." % @article.name) |
224 | referer = Rails.application.routes.recognize_path URI.parse(request.referer).path rescue nil | 234 | referer = Rails.application.routes.recognize_path URI.parse(request.referer).path rescue nil |
225 | if referer and referer[:controller] == 'cms' and referer[:action] != 'edit' | 235 | if referer and referer[:controller] == 'cms' and referer[:action] != 'edit' |
226 | redirect_to referer | 236 | redirect_to referer |
app/controllers/my_profile/memberships_controller.rb
@@ -21,6 +21,9 @@ class MembershipsController < MyProfileController | @@ -21,6 +21,9 @@ class MembershipsController < MyProfileController | ||
21 | @back_to = params[:back_to] || url_for(:action => 'index') | 21 | @back_to = params[:back_to] || url_for(:action => 'index') |
22 | if request.post? && @community.valid? | 22 | if request.post? && @community.valid? |
23 | @community = Community.create_after_moderation(user, params[:community].merge({:environment => environment})) | 23 | @community = Community.create_after_moderation(user, params[:community].merge({:environment => environment})) |
24 | + if @community.new_record? | ||
25 | + session[:notice] = _('Your new community creation request will be evaluated by an administrator. You will be notified.') | ||
26 | + end | ||
24 | redirect_to @back_to | 27 | redirect_to @back_to |
25 | return | 28 | return |
26 | end | 29 | end |
app/controllers/my_profile/profile_design_controller.rb
@@ -3,7 +3,16 @@ class ProfileDesignController < BoxOrganizerController | @@ -3,7 +3,16 @@ class ProfileDesignController < BoxOrganizerController | ||
3 | needs_profile | 3 | needs_profile |
4 | 4 | ||
5 | protect 'edit_profile_design', :profile | 5 | protect 'edit_profile_design', :profile |
6 | - | 6 | + |
7 | + before_filter :protect_fixed_block, :only => [:save, :move_block] | ||
8 | + | ||
9 | + def protect_fixed_block | ||
10 | + block = boxes_holder.blocks.find(params[:id].gsub(/^block-/, '')) | ||
11 | + if block.fixed && !current_person.is_admin? | ||
12 | + render_access_denied | ||
13 | + end | ||
14 | + end | ||
15 | + | ||
7 | def available_blocks | 16 | def available_blocks |
8 | blocks = [ ArticleBlock, TagsBlock, RecentDocumentsBlock, ProfileInfoBlock, LinkListBlock, MyNetworkBlock, FeedReaderBlock, ProfileImageBlock, LocationBlock, SlideshowBlock, ProfileSearchBlock, HighlightsBlock ] | 17 | blocks = [ ArticleBlock, TagsBlock, RecentDocumentsBlock, ProfileInfoBlock, LinkListBlock, MyNetworkBlock, FeedReaderBlock, ProfileImageBlock, LocationBlock, SlideshowBlock, ProfileSearchBlock, HighlightsBlock ] |
9 | 18 |
app/controllers/my_profile/profile_editor_controller.rb
@@ -16,14 +16,16 @@ class ProfileEditorController < MyProfileController | @@ -16,14 +16,16 @@ class ProfileEditorController < MyProfileController | ||
16 | if request.post? | 16 | if request.post? |
17 | params[:profile_data][:fields_privacy] ||= {} if profile.person? && params[:profile_data].is_a?(Hash) | 17 | params[:profile_data][:fields_privacy] ||= {} if profile.person? && params[:profile_data].is_a?(Hash) |
18 | Profile.transaction do | 18 | Profile.transaction do |
19 | - Image.transaction do | ||
20 | - if @profile_data.update_attributes(params[:profile_data]) | ||
21 | - redirect_to :action => 'index', :profile => profile.identifier | ||
22 | - else | ||
23 | - profile.identifier = params[:profile] if profile.identifier.blank? | 19 | + Image.transaction do |
20 | + begin | ||
21 | + @plugins.dispatch(:profile_editor_transaction_extras) | ||
22 | + @profile_data.update_attributes!(params[:profile_data]) | ||
23 | + redirect_to :action => 'index', :profile => profile.identifier | ||
24 | + rescue Exception => ex | ||
25 | + profile.identifier = params[:profile] if profile.identifier.blank? | ||
26 | + end | ||
24 | end | 27 | end |
25 | end | 28 | end |
26 | - end | ||
27 | end | 29 | end |
28 | end | 30 | end |
29 | 31 | ||
@@ -72,10 +74,51 @@ class ProfileEditorController < MyProfileController | @@ -72,10 +74,51 @@ class ProfileEditorController < MyProfileController | ||
72 | if request.post? | 74 | if request.post? |
73 | if @profile.destroy | 75 | if @profile.destroy |
74 | session[:notice] = _('The profile was deleted.') | 76 | session[:notice] = _('The profile was deleted.') |
75 | - redirect_to :controller => 'home' | 77 | + if(params[:return_to]) |
78 | + redirect_to params[:return_to] | ||
79 | + else | ||
80 | + redirect_to :controller => 'home' | ||
81 | + end | ||
76 | else | 82 | else |
77 | session[:notice] = _('Could not delete profile') | 83 | session[:notice] = _('Could not delete profile') |
78 | end | 84 | end |
79 | end | 85 | end |
80 | end | 86 | end |
87 | + | ||
88 | + def deactivate_profile | ||
89 | + if environment.admins.include?(current_person) | ||
90 | + profile = environment.profiles.find(params[:id]) | ||
91 | + if profile.disable | ||
92 | + profile.save | ||
93 | + session[:notice] = _("The profile '#{profile.name}' was deactivated.") | ||
94 | + else | ||
95 | + session[:notice] = _('Could not deactivate profile.') | ||
96 | + end | ||
97 | + end | ||
98 | + | ||
99 | + redirect_to_previous_location | ||
100 | + end | ||
101 | + | ||
102 | + def activate_profile | ||
103 | + if environment.admins.include?(current_person) | ||
104 | + profile = environment.profiles.find(params[:id]) | ||
105 | + | ||
106 | + if profile.enable | ||
107 | + session[:notice] = _("The profile '#{profile.name}' was activated.") | ||
108 | + else | ||
109 | + session[:notice] = _('Could not activate the profile.') | ||
110 | + end | ||
111 | + end | ||
112 | + | ||
113 | + redirect_to_previous_location | ||
114 | + end | ||
115 | + | ||
116 | + protected | ||
117 | + | ||
118 | + def redirect_to_previous_location | ||
119 | + back = request.referer | ||
120 | + back = "/" if back.nil? | ||
121 | + | ||
122 | + redirect_to back | ||
123 | + end | ||
81 | end | 124 | end |
app/controllers/my_profile/profile_members_controller.rb
@@ -20,7 +20,7 @@ class ProfileMembersController < MyProfileController | @@ -20,7 +20,7 @@ class ProfileMembersController < MyProfileController | ||
20 | redirect_to :action => :last_admin | 20 | redirect_to :action => :last_admin |
21 | elsif @person.define_roles(@roles, profile) | 21 | elsif @person.define_roles(@roles, profile) |
22 | session[:notice] = _('Roles successfuly updated') | 22 | session[:notice] = _('Roles successfuly updated') |
23 | - redirect_to :controller => 'profile_editor' | 23 | + redirect_to :action => 'index' |
24 | else | 24 | else |
25 | session[:notice] = _('Couldn\'t change the roles') | 25 | session[:notice] = _('Couldn\'t change the roles') |
26 | redirect_to :action => 'index' | 26 | redirect_to :action => 'index' |
app/controllers/my_profile/tasks_controller.rb
@@ -4,6 +4,7 @@ class TasksController < MyProfileController | @@ -4,6 +4,7 @@ class TasksController < MyProfileController | ||
4 | 4 | ||
5 | def index | 5 | def index |
6 | @filter = params[:filter_type].blank? ? nil : params[:filter_type] | 6 | @filter = params[:filter_type].blank? ? nil : params[:filter_type] |
7 | + @task_types = Task.pending_types_for(profile) | ||
7 | @tasks = Task.to(profile).without_spam.pending.of(@filter).order_by('created_at', 'asc').paginate(:per_page => Task.per_page, :page => params[:page]) | 8 | @tasks = Task.to(profile).without_spam.pending.of(@filter).order_by('created_at', 'asc').paginate(:per_page => Task.per_page, :page => params[:page]) |
8 | @failed = params ? params[:failed] : {} | 9 | @failed = params ? params[:failed] : {} |
9 | end | 10 | end |
app/controllers/public/account_controller.rb
@@ -2,7 +2,7 @@ class AccountController < ApplicationController | @@ -2,7 +2,7 @@ class AccountController < ApplicationController | ||
2 | 2 | ||
3 | no_design_blocks | 3 | no_design_blocks |
4 | 4 | ||
5 | - before_filter :login_required, :only => [:activation_question, :accept_terms, :activate_enterprise] | 5 | + before_filter :login_required, :only => [:activation_question, :accept_terms, :activate_enterprise, :change_password] |
6 | before_filter :redirect_if_logged_in, :only => [:login, :signup] | 6 | before_filter :redirect_if_logged_in, :only => [:login, :signup] |
7 | before_filter :protect_from_bots, :only => :signup | 7 | before_filter :protect_from_bots, :only => :signup |
8 | 8 | ||
@@ -15,11 +15,23 @@ class AccountController < ApplicationController | @@ -15,11 +15,23 @@ class AccountController < ApplicationController | ||
15 | 15 | ||
16 | def activate | 16 | def activate |
17 | @user = User.find_by_activation_code(params[:activation_code]) if params[:activation_code] | 17 | @user = User.find_by_activation_code(params[:activation_code]) if params[:activation_code] |
18 | - if @user and @user.activate | ||
19 | - @message = _("Your account has been activated, now you can log in!") | ||
20 | - check_redirection | ||
21 | - session[:join] = params[:join] unless params[:join].blank? | ||
22 | - render :action => 'login', :userlogin => @user.login | 18 | + if @user |
19 | + unless @user.environment.enabled?('admin_must_approve_new_users') | ||
20 | + if @user.activate | ||
21 | + @message = _("Your account has been activated, now you can log in!") | ||
22 | + check_redirection | ||
23 | + session[:join] = params[:join] unless params[:join].blank? | ||
24 | + render :action => 'login', :userlogin => @user.login | ||
25 | + end | ||
26 | + else | ||
27 | + if @user.create_moderate_task | ||
28 | + session[:notice] = _('Thanks for registering. The administrators were notified.') | ||
29 | + @register_pending = true | ||
30 | + @user.activation_code = nil | ||
31 | + @user.save! | ||
32 | + redirect_to :controller => :home | ||
33 | + end | ||
34 | + end | ||
23 | else | 35 | else |
24 | session[:notice] = _("It looks like you're trying to activate an account. Perhaps have already activated this account?") | 36 | session[:notice] = _("It looks like you're trying to activate an account. Perhaps have already activated this account?") |
25 | redirect_to :controller => :home | 37 | redirect_to :controller => :home |
@@ -85,6 +97,7 @@ class AccountController < ApplicationController | @@ -85,6 +97,7 @@ class AccountController < ApplicationController | ||
85 | @user.return_to = session[:return_to] | 97 | @user.return_to = session[:return_to] |
86 | @person = Person.new(params[:profile_data]) | 98 | @person = Person.new(params[:profile_data]) |
87 | @person.environment = @user.environment | 99 | @person.environment = @user.environment |
100 | + | ||
88 | if request.post? | 101 | if request.post? |
89 | if may_be_a_bot | 102 | if may_be_a_bot |
90 | set_signup_start_time_for_now | 103 | set_signup_start_time_for_now |
@@ -103,11 +116,20 @@ class AccountController < ApplicationController | @@ -103,11 +116,20 @@ class AccountController < ApplicationController | ||
103 | invitation.update_attributes!({:friend => @user.person}) | 116 | invitation.update_attributes!({:friend => @user.person}) |
104 | invitation.finish | 117 | invitation.finish |
105 | end | 118 | end |
119 | + | ||
120 | + unless params[:file].nil? | ||
121 | + image = Image::new :uploaded_data=> params[:file][:image] | ||
122 | + | ||
123 | + @user.person.image = image | ||
124 | + @user.person.save | ||
125 | + end | ||
126 | + | ||
106 | if @user.activated? | 127 | if @user.activated? |
107 | self.current_user = @user | 128 | self.current_user = @user |
108 | check_join_in_community(@user) | 129 | check_join_in_community(@user) |
109 | go_to_signup_initial_page | 130 | go_to_signup_initial_page |
110 | else | 131 | else |
132 | + session[:notice] = _('Thanks for registering!') | ||
111 | @register_pending = true | 133 | @register_pending = true |
112 | end | 134 | end |
113 | end | 135 | end |
@@ -171,7 +193,7 @@ class AccountController < ApplicationController | @@ -171,7 +193,7 @@ class AccountController < ApplicationController | ||
171 | else | 193 | else |
172 | @change_password.errors[:base] << _('Could not find any user with %s equal to "%s".') % [fields_label, params[:value]] | 194 | @change_password.errors[:base] << _('Could not find any user with %s equal to "%s".') % [fields_label, params[:value]] |
173 | end | 195 | end |
174 | - rescue ActiveRecord::RecordInvald | 196 | + rescue ActiveRecord::RecordInvalid |
175 | @change_password.errors[:base] << _('Could not perform password recovery for the user.') | 197 | @change_password.errors[:base] << _('Could not perform password recovery for the user.') |
176 | end | 198 | end |
177 | end | 199 | end |
app/controllers/public/catalog_controller.rb
@@ -11,7 +11,7 @@ class CatalogController < PublicController | @@ -11,7 +11,7 @@ class CatalogController < PublicController | ||
11 | protected | 11 | protected |
12 | 12 | ||
13 | def check_enterprise_and_environment | 13 | def check_enterprise_and_environment |
14 | - unless profile.kind_of?(Enterprise) && @profile.environment.enabled?('products_for_enterprises') | 14 | + unless profile.enterprise? && @profile.environment.enabled?('products_for_enterprises') |
15 | redirect_to :controller => 'profile', :profile => profile.identifier, :action => 'index' | 15 | redirect_to :controller => 'profile', :profile => profile.identifier, :action => 'index' |
16 | end | 16 | end |
17 | end | 17 | end |
app/controllers/public/chat_controller.rb
@@ -19,9 +19,13 @@ class ChatController < PublicController | @@ -19,9 +19,13 @@ class ChatController < PublicController | ||
19 | def avatar | 19 | def avatar |
20 | profile = environment.profiles.find_by_identifier(params[:id]) | 20 | profile = environment.profiles.find_by_identifier(params[:id]) |
21 | filename, mimetype = profile_icon(profile, :minor, true) | 21 | filename, mimetype = profile_icon(profile, :minor, true) |
22 | - data = File.read(File.join(Rails.root, 'public', filename)) | ||
23 | - render :text => data, :layout => false, :content_type => mimetype | ||
24 | - expires_in 24.hours | 22 | + if filename =~ /^(https?:)?\/\// |
23 | + redirect_to filename | ||
24 | + else | ||
25 | + data = File.read(File.join(Rails.root, 'public', filename)) | ||
26 | + render :text => data, :layout => false, :content_type => mimetype | ||
27 | + expires_in 24.hours | ||
28 | + end | ||
25 | end | 29 | end |
26 | 30 | ||
27 | def index | 31 | def index |
app/controllers/public/contact_controller.rb
1 | class ContactController < PublicController | 1 | class ContactController < PublicController |
2 | 2 | ||
3 | - before_filter :login_required | ||
4 | - | ||
5 | needs_profile | 3 | needs_profile |
6 | 4 | ||
7 | def new | 5 | def new |
8 | - @contact | 6 | + @contact = build_contact |
9 | if request.post? && params[:confirm] == 'true' | 7 | if request.post? && params[:confirm] == 'true' |
10 | - @contact = user.build_contact(profile, params[:contact]) | ||
11 | @contact.city = (!params[:city].blank? && City.exists?(params[:city])) ? City.find(params[:city]).name : nil | 8 | @contact.city = (!params[:city].blank? && City.exists?(params[:city])) ? City.find(params[:city]).name : nil |
12 | @contact.state = (!params[:state].blank? && State.exists?(params[:state])) ? State.find(params[:state]).name : nil | 9 | @contact.state = (!params[:state].blank? && State.exists?(params[:state])) ? State.find(params[:state]).name : nil |
13 | if @contact.deliver | 10 | if @contact.deliver |
@@ -16,8 +13,17 @@ class ContactController < PublicController | @@ -16,8 +13,17 @@ class ContactController < PublicController | ||
16 | else | 13 | else |
17 | session[:notice] = _('Contact not sent') | 14 | session[:notice] = _('Contact not sent') |
18 | end | 15 | end |
16 | + end | ||
17 | + end | ||
18 | + | ||
19 | + protected | ||
20 | + | ||
21 | + def build_contact | ||
22 | + params[:contact] ||= {} | ||
23 | + if logged_in? | ||
24 | + user.build_contact profile, params[:contact] | ||
19 | else | 25 | else |
20 | - @contact = user.build_contact(profile) | 26 | + Contact.new params[:contact].merge(dest: profile) |
21 | end | 27 | end |
22 | end | 28 | end |
23 | 29 |
app/controllers/public/content_viewer_controller.rb
@@ -74,7 +74,7 @@ class ContentViewerController < ApplicationController | @@ -74,7 +74,7 @@ class ContentViewerController < ApplicationController | ||
74 | end | 74 | end |
75 | 75 | ||
76 | def versions_diff | 76 | def versions_diff |
77 | - path = params[:page].join('/') | 77 | + path = params[:page] |
78 | @page = profile.articles.find_by_path(path) | 78 | @page = profile.articles.find_by_path(path) |
79 | @v1, @v2 = @page.versions.find_by_version(params[:v1]), @page.versions.find_by_version(params[:v2]) | 79 | @v1, @v2 = @page.versions.find_by_version(params[:v1]), @page.versions.find_by_version(params[:v2]) |
80 | end | 80 | end |
@@ -126,7 +126,7 @@ class ContentViewerController < ApplicationController | @@ -126,7 +126,7 @@ class ContentViewerController < ApplicationController | ||
126 | elsif !@page.display_to?(user) | 126 | elsif !@page.display_to?(user) |
127 | if !profile.public? | 127 | if !profile.public? |
128 | private_profile_partial_parameters | 128 | private_profile_partial_parameters |
129 | - render :template => 'profile/_private_profile', :status => 403 | 129 | + render :template => 'profile/_private_profile', :status => 403, :formats => [:html] |
130 | allowed = false | 130 | allowed = false |
131 | else #if !profile.visible? | 131 | else #if !profile.visible? |
132 | render_access_denied | 132 | render_access_denied |
app/controllers/public/profile_controller.rb
@@ -17,7 +17,11 @@ class ProfileController < PublicController | @@ -17,7 +17,11 @@ class ProfileController < PublicController | ||
17 | end | 17 | end |
18 | @tags = profile.article_tags | 18 | @tags = profile.article_tags |
19 | unless profile.display_info_to?(user) | 19 | unless profile.display_info_to?(user) |
20 | - profile.visible? ? private_profile : invisible_profile | 20 | + if profile.visible? |
21 | + private_profile | ||
22 | + else | ||
23 | + invisible_profile | ||
24 | + end | ||
21 | end | 25 | end |
22 | end | 26 | end |
23 | 27 | ||
@@ -61,13 +65,13 @@ class ProfileController < PublicController | @@ -61,13 +65,13 @@ class ProfileController < PublicController | ||
61 | 65 | ||
62 | def friends | 66 | def friends |
63 | if is_cache_expired?(profile.friends_cache_key(params)) | 67 | if is_cache_expired?(profile.friends_cache_key(params)) |
64 | - @friends = profile.friends.includes(relations_to_include).paginate(:per_page => per_page, :page => params[:npage]) | 68 | + @friends = profile.friends.includes(relations_to_include).paginate(:per_page => per_page, :page => params[:npage], :total_entries => profile.friends.count) |
65 | end | 69 | end |
66 | end | 70 | end |
67 | 71 | ||
68 | def members | 72 | def members |
69 | if is_cache_expired?(profile.members_cache_key(params)) | 73 | if is_cache_expired?(profile.members_cache_key(params)) |
70 | - @members = profile.members_by_name.includes(relations_to_include).paginate(:per_page => members_per_page, :page => params[:npage]) | 74 | + @members = profile.members_by_name.includes(relations_to_include).paginate(:per_page => members_per_page, :page => params[:npage], :total_entries => profile.members.count) |
71 | end | 75 | end |
72 | end | 76 | end |
73 | 77 | ||
@@ -315,7 +319,7 @@ class ProfileController < PublicController | @@ -315,7 +319,7 @@ class ProfileController < PublicController | ||
315 | abuse_report = AbuseReport.new(params[:abuse_report]) | 319 | abuse_report = AbuseReport.new(params[:abuse_report]) |
316 | if !params[:content_type].blank? | 320 | if !params[:content_type].blank? |
317 | article = params[:content_type].constantize.find(params[:content_id]) | 321 | article = params[:content_type].constantize.find(params[:content_id]) |
318 | - abuse_report.content = instance_eval(&article.reported_version) | 322 | + abuse_report.content = article_reported_version(article) |
319 | end | 323 | end |
320 | 324 | ||
321 | user.register_report(abuse_report, profile) | 325 | user.register_report(abuse_report, profile) |
@@ -394,6 +398,7 @@ class ProfileController < PublicController | @@ -394,6 +398,7 @@ class ProfileController < PublicController | ||
394 | 398 | ||
395 | def private_profile | 399 | def private_profile |
396 | private_profile_partial_parameters | 400 | private_profile_partial_parameters |
401 | + render :action => 'index', :status => 403 | ||
397 | end | 402 | end |
398 | 403 | ||
399 | def invisible_profile | 404 | def invisible_profile |
app/controllers/public/search_controller.rb
@@ -90,10 +90,14 @@ class SearchController < PublicController | @@ -90,10 +90,14 @@ class SearchController < PublicController | ||
90 | end | 90 | end |
91 | 91 | ||
92 | def events | 92 | def events |
93 | - year = (params[:year] ? params[:year].to_i : Date.today.year) | ||
94 | - month = (params[:month] ? params[:month].to_i : Date.today.month) | ||
95 | - day = (params[:day] ? params[:day].to_i : Date.today.day) | ||
96 | - @date = build_date(year, month, day) | 93 | + if params[:year].blank? && params[:year].blank? && params[:day].blank? |
94 | + @date = Date.today | ||
95 | + else | ||
96 | + year = (params[:year] ? params[:year].to_i : Date.today.year) | ||
97 | + month = (params[:month] ? params[:month].to_i : Date.today.month) | ||
98 | + day = (params[:day] ? params[:day].to_i : 1) | ||
99 | + @date = build_date(year, month, day) | ||
100 | + end | ||
97 | date_range = (@date - 1.month).at_beginning_of_month..(@date + 1.month).at_end_of_month | 101 | date_range = (@date - 1.month).at_beginning_of_month..(@date + 1.month).at_end_of_month |
98 | 102 | ||
99 | @events = [] | 103 | @events = [] |
app/helpers/application_helper.rb
@@ -304,7 +304,7 @@ module ApplicationHelper | @@ -304,7 +304,7 @@ module ApplicationHelper | ||
304 | def partial_for_class(klass, prefix=nil, suffix=nil) | 304 | def partial_for_class(klass, prefix=nil, suffix=nil) |
305 | raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' if klass.nil? | 305 | raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' if klass.nil? |
306 | name = klass.name.underscore | 306 | name = klass.name.underscore |
307 | - controller.view_paths.reverse_each do |view_path| | 307 | + controller.view_paths.each do |view_path| |
308 | partial = partial_for_class_in_view_path(klass, view_path, prefix, suffix) | 308 | partial = partial_for_class_in_view_path(klass, view_path, prefix, suffix) |
309 | return partial if partial | 309 | return partial if partial |
310 | end | 310 | end |
@@ -312,13 +312,13 @@ module ApplicationHelper | @@ -312,13 +312,13 @@ module ApplicationHelper | ||
312 | raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' | 312 | raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' |
313 | end | 313 | end |
314 | 314 | ||
315 | - def view_for_profile_actions(klass) | ||
316 | - raise ArgumentError, 'No profile actions view for this class.' if klass.nil? | ||
317 | - | ||
318 | - name = klass.name.underscore | ||
319 | - return "blocks/profile_info_actions/" + name + '.html.erb' if File.exists?(Rails.root.join('app', 'views', 'blocks', 'profile_info_actions', name + '.html.erb')) | ||
320 | - | ||
321 | - view_for_profile_actions(klass.superclass) | 315 | + def render_profile_actions klass |
316 | + name = klass.to_s.underscore | ||
317 | + begin | ||
318 | + render "blocks/profile_info_actions/#{name}" | ||
319 | + rescue ActionView::MissingTemplate | ||
320 | + render_profile_actions klass.superclass | ||
321 | + end | ||
322 | end | 322 | end |
323 | 323 | ||
324 | def user | 324 | def user |
@@ -433,19 +433,19 @@ module ApplicationHelper | @@ -433,19 +433,19 @@ module ApplicationHelper | ||
433 | end | 433 | end |
434 | 434 | ||
435 | def theme_site_title | 435 | def theme_site_title |
436 | - theme_include('site_title') | 436 | + @theme_site_title ||= theme_include 'site_title' |
437 | end | 437 | end |
438 | 438 | ||
439 | def theme_header | 439 | def theme_header |
440 | - theme_include('header') | 440 | + @theme_header ||= theme_include 'header' |
441 | end | 441 | end |
442 | 442 | ||
443 | def theme_footer | 443 | def theme_footer |
444 | - theme_include('footer') | 444 | + @theme_footer ||= theme_include 'footer' |
445 | end | 445 | end |
446 | 446 | ||
447 | def theme_extra_navigation | 447 | def theme_extra_navigation |
448 | - theme_include('navigation') | 448 | + @theme_extra_navigation ||= theme_include 'navigation' |
449 | end | 449 | end |
450 | 450 | ||
451 | def is_testing_theme | 451 | def is_testing_theme |
@@ -482,7 +482,12 @@ module ApplicationHelper | @@ -482,7 +482,12 @@ module ApplicationHelper | ||
482 | '/images/icons-app/enterprise-'+ size.to_s() +'.png' | 482 | '/images/icons-app/enterprise-'+ size.to_s() +'.png' |
483 | end | 483 | end |
484 | else | 484 | else |
485 | - '/images/icons-app/person-'+ size.to_s() +'.png' | 485 | + pixels = Image.attachment_options[:thumbnails][size].split('x').first |
486 | + gravatar_profile_image_url( | ||
487 | + profile.email, | ||
488 | + :size => pixels, | ||
489 | + :d => gravatar_default | ||
490 | + ) | ||
486 | end | 491 | end |
487 | filename = default_or_themed_icon(icon) | 492 | filename = default_or_themed_icon(icon) |
488 | end | 493 | end |
@@ -602,7 +607,7 @@ module ApplicationHelper | @@ -602,7 +607,7 @@ module ApplicationHelper | ||
602 | end | 607 | end |
603 | 608 | ||
604 | def gravatar_default | 609 | def gravatar_default |
605 | - (respond_to?(:theme_option) && theme_option.present? && theme_option['gravatar']) || NOOSFERO_CONF['gravatar'] | 610 | + (respond_to?(:theme_option) && theme_option.present? && theme_option['gravatar']) || NOOSFERO_CONF['gravatar'] || 'mm' |
606 | end | 611 | end |
607 | 612 | ||
608 | attr_reader :environment | 613 | attr_reader :environment |
@@ -669,13 +674,14 @@ module ApplicationHelper | @@ -669,13 +674,14 @@ module ApplicationHelper | ||
669 | html.join "\n" | 674 | html.join "\n" |
670 | end | 675 | end |
671 | 676 | ||
677 | + def theme_javascript_src | ||
678 | + script = File.join theme_path, 'theme.js' | ||
679 | + script if File.exists? File.join(Rails.root, 'public', script) | ||
680 | + end | ||
681 | + | ||
672 | def theme_javascript_ng | 682 | def theme_javascript_ng |
673 | - script = File.join(theme_path, 'theme.js') | ||
674 | - if File.exists?(File.join(Rails.root, 'public', script)) | ||
675 | - javascript_include_tag script | ||
676 | - else | ||
677 | - nil | ||
678 | - end | 683 | + script = theme_javascript_src |
684 | + javascript_include_tag script if script | ||
679 | end | 685 | end |
680 | 686 | ||
681 | def file_field_or_thumbnail(label, image, i) | 687 | def file_field_or_thumbnail(label, image, i) |
@@ -856,8 +862,9 @@ module ApplicationHelper | @@ -856,8 +862,9 @@ module ApplicationHelper | ||
856 | end | 862 | end |
857 | 863 | ||
858 | def base_url | 864 | def base_url |
859 | - environment.top_url | 865 | + environment.top_url(request.scheme) |
860 | end | 866 | end |
867 | + alias :top_url :base_url | ||
861 | 868 | ||
862 | def helper_for_article(article) | 869 | def helper_for_article(article) |
863 | article_helper = ActionView::Base.new | 870 | article_helper = ActionView::Base.new |
@@ -902,13 +909,15 @@ module ApplicationHelper | @@ -902,13 +909,15 @@ module ApplicationHelper | ||
902 | end | 909 | end |
903 | 910 | ||
904 | def page_title | 911 | def page_title |
905 | - (@page ? @page.title + ' - ' : '') + | ||
906 | - (@topic ? @topic.title + ' - ' : '') + | ||
907 | - (@section ? @section.title + ' - ' : '') + | ||
908 | - (@toc ? _('Online Manual') + ' - ' : '') + | ||
909 | - (controller.controller_name == 'chat' ? _('Chat') + ' - ' : '') + | ||
910 | - (profile ? profile.short_name : environment.name) + | ||
911 | - (@category ? " - #{@category.full_name}" : '') | 912 | + CGI.escapeHTML( |
913 | + (@page ? @page.title + ' - ' : '') + | ||
914 | + (@topic ? @topic.title + ' - ' : '') + | ||
915 | + (@section ? @section.title + ' - ' : '') + | ||
916 | + (@toc ? _('Online Manual') + ' - ' : '') + | ||
917 | + (controller.controller_name == 'chat' ? _('Chat') + ' - ' : '') + | ||
918 | + (profile ? profile.short_name : environment.name) + | ||
919 | + (@category ? " - #{@category.full_name}" : '') | ||
920 | + ) | ||
912 | end | 921 | end |
913 | 922 | ||
914 | # DEPRECATED. Do not use this. | 923 | # DEPRECATED. Do not use this. |
@@ -937,9 +946,9 @@ module ApplicationHelper | @@ -937,9 +946,9 @@ module ApplicationHelper | ||
937 | # from Article model for an ArticleBlock. | 946 | # from Article model for an ArticleBlock. |
938 | def reference_to_article(text, article, anchor=nil) | 947 | def reference_to_article(text, article, anchor=nil) |
939 | if article.profile.domains.empty? | 948 | if article.profile.domains.empty? |
940 | - href = "/#{article.url[:profile]}/" | 949 | + href = "#{Noosfero.root}/#{article.url[:profile]}/" |
941 | else | 950 | else |
942 | - href = "http://#{article.profile.domains.first.name}/" | 951 | + href = "http://#{article.profile.domains.first.name}#{Noosfero.root}/" |
943 | end | 952 | end |
944 | href += article.url[:page].join('/') | 953 | href += article.url[:page].join('/') |
945 | href += '#' + anchor if anchor | 954 | href += '#' + anchor if anchor |
@@ -1095,7 +1104,7 @@ module ApplicationHelper | @@ -1095,7 +1104,7 @@ module ApplicationHelper | ||
1095 | result | 1104 | result |
1096 | end | 1105 | end |
1097 | 1106 | ||
1098 | - def manage_link(list, kind) | 1107 | + def manage_link(list, kind, title) |
1099 | if list.present? | 1108 | if list.present? |
1100 | link_to_all = nil | 1109 | link_to_all = nil |
1101 | if list.count > 5 | 1110 | if list.count > 5 |
@@ -1108,19 +1117,19 @@ module ApplicationHelper | @@ -1108,19 +1117,19 @@ module ApplicationHelper | ||
1108 | if link_to_all | 1117 | if link_to_all |
1109 | link << link_to_all | 1118 | link << link_to_all |
1110 | end | 1119 | end |
1111 | - render :partial => "shared/manage_link", :locals => {:link => link, :kind => kind.to_s} | 1120 | + render :partial => "shared/manage_link", :locals => {:link => link, :kind => kind.to_s, :title => title} |
1112 | end | 1121 | end |
1113 | end | 1122 | end |
1114 | 1123 | ||
1115 | def manage_enterprises | 1124 | def manage_enterprises |
1116 | return '' unless user && user.environment.enabled?(:display_my_enterprises_on_user_menu) | 1125 | return '' unless user && user.environment.enabled?(:display_my_enterprises_on_user_menu) |
1117 | - manage_link(user.enterprises, :enterprises).to_s | 1126 | + manage_link(user.enterprises, :enterprises, _('My enterprises')).to_s |
1118 | end | 1127 | end |
1119 | 1128 | ||
1120 | def manage_communities | 1129 | def manage_communities |
1121 | return '' unless user && user.environment.enabled?(:display_my_communities_on_user_menu) | 1130 | return '' unless user && user.environment.enabled?(:display_my_communities_on_user_menu) |
1122 | administered_communities = user.communities.more_popular.select {|c| c.admins.include? user} | 1131 | administered_communities = user.communities.more_popular.select {|c| c.admins.include? user} |
1123 | - manage_link(administered_communities, :communities).to_s | 1132 | + manage_link(administered_communities, :communities, _('My communities')).to_s |
1124 | end | 1133 | end |
1125 | 1134 | ||
1126 | def admin_link | 1135 | def admin_link |
@@ -1225,20 +1234,7 @@ module ApplicationHelper | @@ -1225,20 +1234,7 @@ module ApplicationHelper | ||
1225 | def add_zoom_to_images | 1234 | def add_zoom_to_images |
1226 | stylesheet_link_tag('jquery.fancybox') + | 1235 | stylesheet_link_tag('jquery.fancybox') + |
1227 | javascript_include_tag('jquery.fancybox.pack') + | 1236 | javascript_include_tag('jquery.fancybox.pack') + |
1228 | - javascript_tag("jQuery(function($) { | ||
1229 | - $(window).load( function() { | ||
1230 | - $('#article .article-body img').each( function(index) { | ||
1231 | - var original = original_image_dimensions($(this).attr('src')); | ||
1232 | - if ($(this).width() < original['width'] || $(this).height() < original['height']) { | ||
1233 | - $(this).wrap('<div class=\"zoomable-image\" />'); | ||
1234 | - $(this).parent('.zoomable-image').attr('style', $(this).attr('style')); | ||
1235 | - $(this).attr('style', ''); | ||
1236 | - $(this).after(\'<a href=\"' + $(this).attr('src') + '\" class=\"zoomify-image\"><span class=\"zoomify-text\">%s</span></a>'); | ||
1237 | - } | ||
1238 | - }); | ||
1239 | - $('.zoomify-image').fancybox(); | ||
1240 | - }); | ||
1241 | - });" % _('Zoom in')) | 1237 | + javascript_tag("apply_zoom_to_images(#{_('Zoom in').to_json})") |
1242 | end | 1238 | end |
1243 | 1239 | ||
1244 | def render_dialog_error_messages(instance_name) | 1240 | def render_dialog_error_messages(instance_name) |
@@ -1293,11 +1289,13 @@ module ApplicationHelper | @@ -1293,11 +1289,13 @@ module ApplicationHelper | ||
1293 | end | 1289 | end |
1294 | 1290 | ||
1295 | def delete_article_message(article) | 1291 | def delete_article_message(article) |
1296 | - if article.folder? | ||
1297 | - _("Are you sure that you want to remove the folder \"#{article.name}\"? Note that all the items inside it will also be removed!") | ||
1298 | - else | ||
1299 | - _("Are you sure that you want to remove the item \"#{article.name}\"?") | ||
1300 | - end | 1292 | + CGI.escapeHTML( |
1293 | + if article.folder? | ||
1294 | + _("Are you sure that you want to remove the folder \"%s\"? Note that all the items inside it will also be removed!") % article.name | ||
1295 | + else | ||
1296 | + _("Are you sure that you want to remove the item \"%s\"?") % article.name | ||
1297 | + end | ||
1298 | + ) | ||
1301 | end | 1299 | end |
1302 | 1300 | ||
1303 | def expirable_link_to(expired, content, url, options = {}) | 1301 | def expirable_link_to(expired, content, url, options = {}) |
@@ -1318,10 +1316,8 @@ module ApplicationHelper | @@ -1318,10 +1316,8 @@ module ApplicationHelper | ||
1318 | return '' if templates.count == 0 | 1316 | return '' if templates.count == 0 |
1319 | return hidden_field_tag("#{field_name}[template_id]", templates.first.id) if templates.count == 1 | 1317 | return hidden_field_tag("#{field_name}[template_id]", templates.first.id) if templates.count == 1 |
1320 | 1318 | ||
1321 | - counter = 0 | ||
1322 | radios = templates.map do |template| | 1319 | radios = templates.map do |template| |
1323 | - counter += 1 | ||
1324 | - content_tag('li', labelled_radio_button(link_to(template.name, template.url, :target => '_blank'), "#{field_name}[template_id]", template.id, counter==1)) | 1320 | + content_tag('li', labelled_radio_button(link_to(template.name, template.url, :target => '_blank'), "#{field_name}[template_id]", template.id, environment.is_default_template?(template))) |
1325 | end.join("\n") | 1321 | end.join("\n") |
1326 | 1322 | ||
1327 | content_tag('div', content_tag('label', _('Profile organization'), :for => 'template-options', :class => 'formlabel') + | 1323 | content_tag('div', content_tag('label', _('Profile organization'), :for => 'template-options', :class => 'formlabel') + |
@@ -1373,7 +1369,7 @@ module ApplicationHelper | @@ -1373,7 +1369,7 @@ module ApplicationHelper | ||
1373 | @message = _("The content here is available to %s's friends only.") % profile.short_name | 1369 | @message = _("The content here is available to %s's friends only.") % profile.short_name |
1374 | else | 1370 | else |
1375 | @action = :join | 1371 | @action = :join |
1376 | - @message = _('The contents in this community is available to members only.') | 1372 | + @message = _('The contents in this profile is available to members only.') |
1377 | end | 1373 | end |
1378 | @no_design_blocks = true | 1374 | @no_design_blocks = true |
1379 | end | 1375 | end |
@@ -1385,7 +1381,7 @@ module ApplicationHelper | @@ -1385,7 +1381,7 @@ module ApplicationHelper | ||
1385 | # are old things that do not support it we are keeping this hot spot. | 1381 | # are old things that do not support it we are keeping this hot spot. |
1386 | html = @plugins.pipeline(:parse_content, html, source).first | 1382 | html = @plugins.pipeline(:parse_content, html, source).first |
1387 | end | 1383 | end |
1388 | - html | 1384 | + html && html.html_safe |
1389 | end | 1385 | end |
1390 | 1386 | ||
1391 | def convert_macro(html, source) | 1387 | def convert_macro(html, source) |
@@ -1415,4 +1411,14 @@ module ApplicationHelper | @@ -1415,4 +1411,14 @@ module ApplicationHelper | ||
1415 | content_tag('ul', article.versions.map {|v| link_to("r#{v.version}", @page.url.merge(:version => v.version))}) | 1411 | content_tag('ul', article.versions.map {|v| link_to("r#{v.version}", @page.url.merge(:version => v.version))}) |
1416 | end | 1412 | end |
1417 | 1413 | ||
1414 | + def labelled_colorpicker_field(human_name, object_name, method, options = {}) | ||
1415 | + options[:id] ||= 'text-field-' + FormsHelper.next_id_number | ||
1416 | + content_tag('label', human_name, :for => options[:id], :class => 'formlabel') + | ||
1417 | + colorpicker_field(object_name, method, options.merge(:class => 'colorpicker_field')) | ||
1418 | + end | ||
1419 | + | ||
1420 | + def colorpicker_field(object_name, method, options = {}) | ||
1421 | + text_field(object_name, method, options.merge(:class => 'colorpicker_field')) | ||
1422 | + end | ||
1423 | + | ||
1418 | end | 1424 | end |
app/helpers/article_helper.rb
@@ -3,6 +3,12 @@ module ArticleHelper | @@ -3,6 +3,12 @@ module ArticleHelper | ||
3 | include PrototypeHelper | 3 | include PrototypeHelper |
4 | include TokenHelper | 4 | include TokenHelper |
5 | 5 | ||
6 | + def article_reported_version(article) | ||
7 | + search_path = Rails.root.join('app', 'views', 'shared', 'reported_versions') | ||
8 | + partial_path = File.join('shared', 'reported_versions', 'profile', partial_for_class_in_view_path(article.class, search_path)) | ||
9 | + render_to_string(:partial => partial_path, :locals => {:article => article}) | ||
10 | + end | ||
11 | + | ||
6 | def custom_options_for_article(article, tokenized_children) | 12 | def custom_options_for_article(article, tokenized_children) |
7 | @article = article | 13 | @article = article |
8 | 14 | ||
@@ -71,18 +77,69 @@ module ArticleHelper | @@ -71,18 +77,69 @@ module ArticleHelper | ||
71 | content_tag('div', | 77 | content_tag('div', |
72 | radio_button(:article, :published, false) + | 78 | radio_button(:article, :published, false) + |
73 | content_tag('label', _('Private'), :for => 'article_published_false', :id => "label_private") | 79 | content_tag('label', _('Private'), :for => 'article_published_false', :id => "label_private") |
74 | - ) + | ||
75 | - (article.profile.community? ? content_tag('div', | ||
76 | - content_tag('label', _('Fill in the search field to add the exception users to see this content'), :id => "text-input-search-exception-users") + | ||
77 | - token_input_field_tag(:q, 'search-article-privacy-exceptions', {:action => 'search_article_privacy_exceptions'}, | ||
78 | - {:focus => false, :hint_text => _('Type in a search term for a user'), :pre_populate => tokenized_children})) : | ||
79 | - '')) | 80 | + ) + |
81 | + privacity_exceptions(article, tokenized_children) | ||
82 | + ) | ||
83 | + end | ||
84 | + | ||
85 | + def privacity_exceptions(article, tokenized_children) | ||
86 | + content_tag('div', | ||
87 | + content_tag('div', | ||
88 | + ( | ||
89 | + if article.profile | ||
90 | + add_option_to_followers(article, tokenized_children) | ||
91 | + else | ||
92 | + '' | ||
93 | + end | ||
94 | + ) | ||
95 | + ), | ||
96 | + :style => "margin-left:10px" | ||
97 | + ) | ||
98 | + end | ||
99 | + | ||
100 | + def add_option_to_followers(article, tokenized_children) | ||
101 | + label_message = article.profile.organization? ? _('For all community members') : _('For all your friends') | ||
102 | + | ||
103 | + check_box( | ||
104 | + :article, | ||
105 | + :show_to_followers, | ||
106 | + {:class => "custom_privacy_option"} | ||
107 | + ) + | ||
108 | + content_tag( | ||
109 | + 'label', | ||
110 | + label_message, | ||
111 | + :for => 'article_show_to_followers', | ||
112 | + :id => 'label_show_to_followers' | ||
113 | + ) + | ||
114 | + (article.profile.community? ? | ||
115 | + content_tag( | ||
116 | + 'div', | ||
117 | + content_tag( | ||
118 | + 'label', | ||
119 | + _('Fill in the search field to add the exception users to see this content'), | ||
120 | + :id => "text-input-search-exception-users" | ||
121 | + ) + | ||
122 | + token_input_field_tag( | ||
123 | + :q, | ||
124 | + 'search-article-privacy-exceptions', | ||
125 | + {:action => 'search_article_privacy_exceptions'}, | ||
126 | + { | ||
127 | + :focus => false, | ||
128 | + :hint_text => _('Type in a search term for a user'), | ||
129 | + :pre_populate => tokenized_children | ||
130 | + } | ||
131 | + ) | ||
132 | + ) : '') | ||
80 | end | 133 | end |
81 | 134 | ||
82 | def prepare_to_token_input(array) | 135 | def prepare_to_token_input(array) |
83 | array.map { |object| {:id => object.id, :name => object.name} } | 136 | array.map { |object| {:id => object.id, :name => object.name} } |
84 | end | 137 | end |
85 | 138 | ||
139 | + def prepare_to_token_input_by_label(array) | ||
140 | + array.map { |object| {:label => object.name, :value => object.name} } | ||
141 | + end | ||
142 | + | ||
86 | def cms_label_for_new_children | 143 | def cms_label_for_new_children |
87 | _('New article') | 144 | _('New article') |
88 | end | 145 | end |
app/helpers/block_helper.rb
@@ -6,19 +6,20 @@ module BlockHelper | @@ -6,19 +6,20 @@ module BlockHelper | ||
6 | content_tag 'h3', content_tag('span', h(title)), :class => tag_class | 6 | content_tag 'h3', content_tag('span', h(title)), :class => tag_class |
7 | end | 7 | end |
8 | 8 | ||
9 | - def highlights_block_config_image_fields(block, image={}) | 9 | + def highlights_block_config_image_fields(block, image={}, row_number=nil) |
10 | " | 10 | " |
11 | - <tr class=\"image-data-line\"> | 11 | + <tr class=\"image-data-line\" data-row-number='#{row_number}'> |
12 | <td> | 12 | <td> |
13 | #{select_tag 'block[images][][image_id]', content_tag(:option) + option_groups_from_collection_for_select(block.folder_choices, :images, :name, :id, :name, image[:image_id].to_i).html_safe} | 13 | #{select_tag 'block[images][][image_id]', content_tag(:option) + option_groups_from_collection_for_select(block.folder_choices, :images, :name, :id, :name, image[:image_id].to_i).html_safe} |
14 | </td> | 14 | </td> |
15 | <td>#{text_field_tag 'block[images][][address]', image[:address], :class => 'highlight-address', :size => 20}</td> | 15 | <td>#{text_field_tag 'block[images][][address]', image[:address], :class => 'highlight-address', :size => 20}</td> |
16 | <td>#{text_field_tag 'block[images][][position]', image[:position], :class => 'highlight-position', :size => 1}</td> | 16 | <td>#{text_field_tag 'block[images][][position]', image[:position], :class => 'highlight-position', :size => 1}</td> |
17 | - </tr><tr class=\"image-title\"> | 17 | + </tr><tr class=\"image-title\" data-row-number='#{row_number}'> |
18 | <td colspan=\"3\"><label>#{ | 18 | <td colspan=\"3\"><label>#{ |
19 | content_tag('span', _('Title')) + | 19 | content_tag('span', _('Title')) + |
20 | text_field_tag('block[images][][title]', image[:title], :class => 'highlight-title', :size => 45) | 20 | text_field_tag('block[images][][title]', image[:title], :class => 'highlight-title', :size => 45) |
21 | }</label></td> | 21 | }</label></td> |
22 | + <td>#{link_to '', '#', :class=>'button icon-button icon-delete delete-highlight', :confirm=>_('Are you sure you want to remove this highlight')}</td> | ||
22 | </tr> | 23 | </tr> |
23 | " | 24 | " |
24 | end | 25 | end |
app/helpers/blog_helper.rb
@@ -17,13 +17,13 @@ module BlogHelper | @@ -17,13 +17,13 @@ module BlogHelper | ||
17 | _('Configure blog') | 17 | _('Configure blog') |
18 | end | 18 | end |
19 | 19 | ||
20 | - def list_posts(articles, format = 'full') | 20 | + def list_posts(articles, format = 'full', paginate = true) |
21 | pagination = will_paginate(articles, { | 21 | pagination = will_paginate(articles, { |
22 | :param_name => 'npage', | 22 | :param_name => 'npage', |
23 | :previous_label => _('« Newer posts'), | 23 | :previous_label => _('« Newer posts'), |
24 | :next_label => _('Older posts »'), | 24 | :next_label => _('Older posts »'), |
25 | :params => {:action=>"view_page", :page=>articles.first.parent.path.split('/'), :controller=>"content_viewer"} | 25 | :params => {:action=>"view_page", :page=>articles.first.parent.path.split('/'), :controller=>"content_viewer"} |
26 | - }) if articles.present? | 26 | + }) if articles.present? && paginate |
27 | content = [] | 27 | content = [] |
28 | artic_len = articles.length | 28 | artic_len = articles.length |
29 | articles.each_with_index{ |art,i| | 29 | articles.each_with_index{ |art,i| |
@@ -45,9 +45,9 @@ module BlogHelper | @@ -45,9 +45,9 @@ module BlogHelper | ||
45 | 45 | ||
46 | def display_post(article, format = 'full') | 46 | def display_post(article, format = 'full') |
47 | no_comments = (format == 'full') ? false : true | 47 | no_comments = (format == 'full') ? false : true |
48 | + title = article_title(article, :no_comments => no_comments) | ||
48 | html = send("display_#{format}_format", FilePresenter.for(article)).html_safe | 49 | html = send("display_#{format}_format", FilePresenter.for(article)).html_safe |
49 | - | ||
50 | - article_title(article, :no_comments => no_comments) + html | 50 | + title + html |
51 | end | 51 | end |
52 | 52 | ||
53 | def display_full_format(article) | 53 | def display_full_format(article) |
app/helpers/boxes_helper.rb
@@ -170,49 +170,54 @@ module BoxesHelper | @@ -170,49 +170,54 @@ module BoxesHelper | ||
170 | else | 170 | else |
171 | "before-block-#{block.id}" | 171 | "before-block-#{block.id}" |
172 | end | 172 | end |
173 | - | ||
174 | - content_tag('div', ' ', :id => id, :class => 'block-target' ) + drop_receiving_element(id, :url => { :action => 'move_block', :target => id }, :accept => box.acceptable_blocks, :hoverclass => 'block-target-hover') | 173 | + if block.nil? or modifiable?(block) |
174 | + content_tag('div', ' ', :id => id, :class => 'block-target' ) + drop_receiving_element(id, :url => { :action => 'move_block', :target => id }, :accept => box.acceptable_blocks, :hoverclass => 'block-target-hover') | ||
175 | + else | ||
176 | + "" | ||
177 | + end | ||
175 | end | 178 | end |
176 | 179 | ||
177 | # makes the given block draggable so it can be moved away. | 180 | # makes the given block draggable so it can be moved away. |
178 | def block_handle(block) | 181 | def block_handle(block) |
179 | - draggable_element("block-#{block.id}", :revert => true) | 182 | + modifiable?(block) ? draggable_element("block-#{block.id}", :revert => true) : "" |
180 | end | 183 | end |
181 | 184 | ||
182 | def block_edit_buttons(block) | 185 | def block_edit_buttons(block) |
183 | buttons = [] | 186 | buttons = [] |
184 | nowhere = 'javascript: return false;' | 187 | nowhere = 'javascript: return false;' |
185 | 188 | ||
186 | - if block.first? | ||
187 | - buttons << icon_button('up-disabled', _("Can't move up anymore."), nowhere) | ||
188 | - else | ||
189 | - buttons << icon_button('up', _('Move block up'), { :action => 'move_block_up', :id => block.id }, { :method => 'post' }) | ||
190 | - end | 189 | + if modifiable?(block) |
190 | + if block.first? | ||
191 | + buttons << icon_button('up-disabled', _("Can't move up anymore."), nowhere) | ||
192 | + else | ||
193 | + buttons << icon_button('up', _('Move block up'), { :action => 'move_block_up', :id => block.id }, { :method => 'post' }) | ||
194 | + end | ||
191 | 195 | ||
192 | - if block.last? | ||
193 | - buttons << icon_button('down-disabled', _("Can't move down anymore."), nowhere) | ||
194 | - else | ||
195 | - buttons << icon_button(:down, _('Move block down'), { :action => 'move_block_down' ,:id => block.id }, { :method => 'post'}) | ||
196 | - end | 196 | + if block.last? |
197 | + buttons << icon_button('down-disabled', _("Can't move down anymore."), nowhere) | ||
198 | + else | ||
199 | + buttons << icon_button(:down, _('Move block down'), { :action => 'move_block_down' ,:id => block.id }, { :method => 'post'}) | ||
200 | + end | ||
197 | 201 | ||
198 | - holder = block.owner | ||
199 | - # move to opposite side | ||
200 | - # FIXME too much hardcoded stuff | ||
201 | - if holder.layout_template == 'default' | ||
202 | - if block.box.position == 2 # area 2, left side => move to right side | ||
203 | - buttons << icon_button('right', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[2].id.to_s, :id => block.id }, :method => 'post' ) | ||
204 | - elsif block.box.position == 3 # area 3, right side => move to left side | ||
205 | - buttons << icon_button('left', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[1].id.to_s, :id => block.id }, :method => 'post' ) | 202 | + holder = block.owner |
203 | + # move to opposite side | ||
204 | + # FIXME too much hardcoded stuff | ||
205 | + if holder.layout_template == 'default' | ||
206 | + if block.box.position == 2 # area 2, left side => move to right side | ||
207 | + buttons << icon_button('right', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[2].id.to_s, :id => block.id }, :method => 'post' ) | ||
208 | + elsif block.box.position == 3 # area 3, right side => move to left side | ||
209 | + buttons << icon_button('left', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[1].id.to_s, :id => block.id }, :method => 'post' ) | ||
210 | + end | ||
206 | end | 211 | end |
207 | - end | ||
208 | 212 | ||
209 | - if block.editable? | ||
210 | - buttons << colorbox_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id }) | ||
211 | - end | 213 | + if block.editable? |
214 | + buttons << colorbox_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id }) | ||
215 | + end | ||
212 | 216 | ||
213 | - if !block.main? | ||
214 | - buttons << icon_button(:delete, _('Remove block'), { :action => 'remove', :id => block.id }, { :method => 'post', :confirm => _('Are you sure you want to remove this block?')}) | ||
215 | - buttons << icon_button(:clone, _('Clone'), { :action => 'clone_block', :id => block.id }, { :method => 'post' }) | 217 | + if !block.main? |
218 | + buttons << icon_button(:delete, _('Remove block'), { :action => 'remove', :id => block.id }, { :method => 'post', :confirm => _('Are you sure you want to remove this block?')}) | ||
219 | + buttons << icon_button(:clone, _('Clone'), { :action => 'clone_block', :id => block.id }, { :method => 'post' }) | ||
220 | + end | ||
216 | end | 221 | end |
217 | 222 | ||
218 | if block.respond_to?(:help) | 223 | if block.respond_to?(:help) |
@@ -248,5 +253,7 @@ module BoxesHelper | @@ -248,5 +253,7 @@ module BoxesHelper | ||
248 | classes | 253 | classes |
249 | end | 254 | end |
250 | 255 | ||
251 | - | 256 | + def modifiable?(block) |
257 | + return !block.fixed || environment.admins.include?(user) | ||
258 | + end | ||
252 | end | 259 | end |
app/helpers/categories_helper.rb
1 | module CategoriesHelper | 1 | module CategoriesHelper |
2 | 2 | ||
3 | - | ||
4 | - COLORS = [ | ||
5 | - [ N_('Do not display at the menu'), nil ], | ||
6 | - [ N_('Orange'), 1], | ||
7 | - [ N_('Green'), 2], | ||
8 | - [ N_('Purple'), 3], | ||
9 | - [ N_('Red'), 4], | ||
10 | - [ N_('Dark Green'), 5], | ||
11 | - [ N_('Blue Oil'), 6], | ||
12 | - [ N_('Blue'), 7], | ||
13 | - [ N_('Brown'), 8], | ||
14 | - [ N_('Light Green'), 9], | ||
15 | - [ N_('Light Blue'), 10], | ||
16 | - [ N_('Dark Blue'), 11], | ||
17 | - [ N_('Blue Pool'), 12], | ||
18 | - [ N_('Beige'), 13], | ||
19 | - [ N_('Yellow'), 14], | ||
20 | - [ N_('Light Brown'), 15] | ||
21 | - ] | ||
22 | - | ||
23 | TYPES = [ | 3 | TYPES = [ |
24 | [ _('General Category'), Category.to_s ], | 4 | [ _('General Category'), Category.to_s ], |
25 | [ _('Product Category'), ProductCategory.to_s ], | 5 | [ _('Product Category'), ProductCategory.to_s ], |
26 | [ _('Region'), Region.to_s ], | 6 | [ _('Region'), Region.to_s ], |
27 | ] | 7 | ] |
28 | 8 | ||
29 | - def select_color_for_category | ||
30 | - if @category.top_level? | ||
31 | - labelled_form_field(_('Display at the menu?'), select('category', 'display_color', CategoriesHelper::COLORS.map {|item| [gettext(item[0]), item[1]] })) | ||
32 | - else | ||
33 | - "" | ||
34 | - end | ||
35 | - end | ||
36 | - | ||
37 | - def display_color_for_category(category) | ||
38 | - color = category.display_color | ||
39 | - if color.nil? | ||
40 | - "" | ||
41 | - else | ||
42 | - "[" + gettext(CategoriesHelper::COLORS.find {|item| item[1] == color}.first) + "]" | ||
43 | - end | ||
44 | - end | ||
45 | - | ||
46 | def select_category_type(field) | 9 | def select_category_type(field) |
47 | value = params[field] | 10 | value = params[field] |
48 | labelled_form_field(_('Type of category'), select_tag('type', options_for_select(TYPES, value))) | 11 | labelled_form_field(_('Type of category'), select_tag('type', options_for_select(TYPES, value))) |
49 | end | 12 | end |
50 | 13 | ||
14 | + def category_color_style(category) | ||
15 | + return '' if category.nil? or category.display_color.blank? | ||
16 | + 'background-color: #'+category.display_color+';' | ||
17 | + end | ||
18 | + | ||
51 | #FIXME make this test | 19 | #FIXME make this test |
52 | def selected_category_link(cat) | 20 | def selected_category_link(cat) |
53 | js_remove = "jQuery('#selected-category-#{cat.id}').remove();" | 21 | js_remove = "jQuery('#selected-category-#{cat.id}').remove();" |
app/helpers/content_viewer_helper.rb
@@ -10,7 +10,7 @@ module ContentViewerHelper | @@ -10,7 +10,7 @@ module ContentViewerHelper | ||
10 | end | 10 | end |
11 | 11 | ||
12 | def number_of_comments(article) | 12 | def number_of_comments(article) |
13 | - display_number_of_comments(article.comments.without_spam.count) | 13 | + display_number_of_comments(article.comments_count - article.spam_comments_count.to_i) |
14 | end | 14 | end |
15 | 15 | ||
16 | def article_title(article, args = {}) | 16 | def article_title(article, args = {}) |
@@ -26,7 +26,7 @@ module ContentViewerHelper | @@ -26,7 +26,7 @@ module ContentViewerHelper | ||
26 | end | 26 | end |
27 | title << content_tag('span', | 27 | title << content_tag('span', |
28 | content_tag('span', show_date(article.published_at), :class => 'date') + | 28 | content_tag('span', show_date(article.published_at), :class => 'date') + |
29 | - content_tag('span', _(", by %s") % link_to(article.author_name, article.author_url), :class => 'author') + | 29 | + content_tag('span', _(", by %s") % (article.author ? link_to(article.author_name, article.author_url) : article.author_name), :class => 'author') + |
30 | content_tag('span', comments, :class => 'comments'), | 30 | content_tag('span', comments, :class => 'comments'), |
31 | :class => 'created-at' | 31 | :class => 'created-at' |
32 | ) | 32 | ) |
@@ -45,7 +45,7 @@ module ContentViewerHelper | @@ -45,7 +45,7 @@ module ContentViewerHelper | ||
45 | { article.environment.locales[translation.language] => { :href => url_for(translation.url) } } | 45 | { article.environment.locales[translation.language] => { :href => url_for(translation.url) } } |
46 | end | 46 | end |
47 | content_tag(:div, link_to(_('Translations'), '#', | 47 | content_tag(:div, link_to(_('Translations'), '#', |
48 | - :onmouseover => "toggleSubmenu(this, '#{_('Translations')}', #{links.to_json}); return false", | 48 | + :onmouseover => "toggleSubmenu(this, '#{_('Translations')}', #{CGI::escape_html(links.to_json)}); return false", |
49 | :class => 'article-translations-menu simplemenu-trigger up'), | 49 | :class => 'article-translations-menu simplemenu-trigger up'), |
50 | :class => 'article-translations') | 50 | :class => 'article-translations') |
51 | end | 51 | end |
app/helpers/folder_helper.rb
@@ -5,15 +5,17 @@ module FolderHelper | @@ -5,15 +5,17 @@ module FolderHelper | ||
5 | include ShortFilename | 5 | include ShortFilename |
6 | include ArticleHelper | 6 | include ArticleHelper |
7 | 7 | ||
8 | - def list_articles(articles, recursive = false) | ||
9 | - if !articles.blank? | ||
10 | - articles = articles.paginate( | 8 | + def list_contents(configure={}) |
9 | + configure[:recursive] ||= false | ||
10 | + configure[:list_type] ||= :folder | ||
11 | + if !configure[:contents].blank? | ||
12 | + configure[:contents] = configure[:contents].paginate( | ||
11 | :order => "updated_at DESC", | 13 | :order => "updated_at DESC", |
12 | :per_page => 10, | 14 | :per_page => 10, |
13 | :page => params[:npage] | 15 | :page => params[:npage] |
14 | ) | 16 | ) |
15 | 17 | ||
16 | - render :file => 'shared/articles_list', :locals => {:articles => articles, :recursive => recursive} | 18 | + render :file => 'shared/content_list', :locals => configure |
17 | else | 19 | else |
18 | content_tag('em', _('(empty folder)')) | 20 | content_tag('em', _('(empty folder)')) |
19 | end | 21 | end |
@@ -23,21 +25,33 @@ module FolderHelper | @@ -23,21 +25,33 @@ module FolderHelper | ||
23 | articles.select {|article| article.display_to?(user)} | 25 | articles.select {|article| article.display_to?(user)} |
24 | end | 26 | end |
25 | 27 | ||
26 | - def display_article_in_listing(article, recursive = false, level = 0) | ||
27 | - article = FilePresenter.for article | ||
28 | - article_link = if article.image? | ||
29 | - link_to(' ' * (level * 4) + image_tag(icon_for_article(article)) + short_filename(article.name), article.url.merge(:view => true)) | 28 | + def display_content_in_listing(configure={}) |
29 | + recursive = configure[:recursive] || false | ||
30 | + list_type = configure[:list_type] || :folder | ||
31 | + level = configure[:level] || 0 | ||
32 | + content = FilePresenter.for configure[:content] | ||
33 | + content_link = if content.image? | ||
34 | + link_to(' ' * (level * 4) + | ||
35 | + image_tag(icon_for_article(content)) + short_filename(content.name), | ||
36 | + content.url.merge(:view => true) | ||
37 | + ) | ||
30 | else | 38 | else |
31 | - link_to(' ' * (level * 4) + short_filename(article.name), article.url.merge(:view => true), :class => icon_for_article(article)) | 39 | + link_to(' ' * (level * 4) + |
40 | + short_filename(content.name), | ||
41 | + content.url.merge(:view => true), :class => icon_for_article(content) | ||
42 | + ) | ||
32 | end | 43 | end |
33 | result = content_tag( | 44 | result = content_tag( |
34 | 'tr', | 45 | 'tr', |
35 | - content_tag('td', article_link )+ | ||
36 | - content_tag('td', show_date(article.updated_at), :class => 'last-update'), | ||
37 | - :class => 'sitemap-item' | 46 | + content_tag('td', content_link ) + |
47 | + content_tag('td', show_date(content.updated_at), :class => 'last-update'), | ||
48 | + :class => "#{list_type}-item" | ||
38 | ) | 49 | ) |
39 | if recursive | 50 | if recursive |
40 | - result + article.children.map {|item| display_article_in_listing(item, recursive, level + 1) }.join('') | 51 | + result + content.children.map {|item| |
52 | + display_content_in_listing :content=>item, :recursive=>recursive, | ||
53 | + :list_type=>list_type, :level=>level+1 | ||
54 | + }.join("\n") | ||
41 | else | 55 | else |
42 | result | 56 | result |
43 | end | 57 | end |
app/helpers/layout_helper.rb
@@ -2,12 +2,31 @@ module LayoutHelper | @@ -2,12 +2,31 @@ module LayoutHelper | ||
2 | 2 | ||
3 | def body_classes | 3 | def body_classes |
4 | # Identify the current controller and action for the CSS: | 4 | # Identify the current controller and action for the CSS: |
5 | + (logged_in? ? " logged-in" : "") + | ||
5 | " controller-#{controller.controller_name}" + | 6 | " controller-#{controller.controller_name}" + |
6 | " action-#{controller.controller_name}-#{controller.action_name}" + | 7 | " action-#{controller.controller_name}-#{controller.action_name}" + |
7 | " template-#{@layout_template || if profile.blank? then 'default' else profile.layout_template end}" + | 8 | " template-#{@layout_template || if profile.blank? then 'default' else profile.layout_template end}" + |
8 | (!profile.nil? && profile.is_on_homepage?(request.path,@page) ? " profile-homepage" : "") | 9 | (!profile.nil? && profile.is_on_homepage?(request.path,@page) ? " profile-homepage" : "") |
9 | end | 10 | end |
10 | 11 | ||
12 | + def html_tag_classes | ||
13 | + [ | ||
14 | + body_classes, ( | ||
15 | + profile.blank? ? nil : [ | ||
16 | + 'profile-type-is-' + profile.class.name.downcase, | ||
17 | + 'profile-name-is-' + profile.identifier, | ||
18 | + ] | ||
19 | + ), 'theme-' + current_theme, | ||
20 | + @plugins.dispatch(:html_tag_classes).map do |content| | ||
21 | + if content.respond_to?(:call) | ||
22 | + instance_exec(&content) | ||
23 | + else | ||
24 | + content.html_safe | ||
25 | + end | ||
26 | + end | ||
27 | + ].flatten.compact.join(' ') | ||
28 | + end | ||
29 | + | ||
11 | def noosfero_javascript | 30 | def noosfero_javascript |
12 | plugins_javascripts = @plugins.map { |plugin| [plugin.js_files].flatten.map { |js| plugin.class.public_path(js) } }.flatten | 31 | plugins_javascripts = @plugins.map { |plugin| [plugin.js_files].flatten.map { |js| plugin.class.public_path(js) } }.flatten |
13 | 32 | ||
@@ -17,6 +36,8 @@ module LayoutHelper | @@ -17,6 +36,8 @@ module LayoutHelper | ||
17 | unless plugins_javascripts.empty? | 36 | unless plugins_javascripts.empty? |
18 | output += javascript_include_tag plugins_javascripts, :cache => "cache/plugins-#{Digest::MD5.hexdigest plugins_javascripts.to_s}" | 37 | output += javascript_include_tag plugins_javascripts, :cache => "cache/plugins-#{Digest::MD5.hexdigest plugins_javascripts.to_s}" |
19 | end | 38 | end |
39 | + output += theme_javascript_ng.to_s | ||
40 | + | ||
20 | output | 41 | output |
21 | end | 42 | end |
22 | 43 | ||
@@ -27,6 +48,7 @@ module LayoutHelper | @@ -27,6 +48,7 @@ module LayoutHelper | ||
27 | 'thickbox', | 48 | 'thickbox', |
28 | 'lightbox', | 49 | 'lightbox', |
29 | 'colorbox', | 50 | 'colorbox', |
51 | + 'inputosaurus', | ||
30 | pngfix_stylesheet_path, | 52 | pngfix_stylesheet_path, |
31 | ] + tokeninput_stylesheets | 53 | ] + tokeninput_stylesheets |
32 | plugins_stylesheets = @plugins.select(&:stylesheet?).map { |plugin| plugin.class.public_path('style.css') } | 54 | plugins_stylesheets = @plugins.select(&:stylesheet?).map { |plugin| plugin.class.public_path('style.css') } |
@@ -83,6 +105,10 @@ module LayoutHelper | @@ -83,6 +105,10 @@ module LayoutHelper | ||
83 | theme_path + '/style.css' | 105 | theme_path + '/style.css' |
84 | end | 106 | end |
85 | 107 | ||
108 | + def layout_template | ||
109 | + if profile then profile.layout_template else environment.layout_template end | ||
110 | + end | ||
111 | + | ||
86 | def addthis_javascript | 112 | def addthis_javascript |
87 | if NOOSFERO_CONF['addthis_enabled'] | 113 | if NOOSFERO_CONF['addthis_enabled'] |
88 | '<script src="https://s7.addthis.com/js/152/addthis_widget.js"></script>' | 114 | '<script src="https://s7.addthis.com/js/152/addthis_widget.js"></script>' |
@@ -90,7 +116,7 @@ module LayoutHelper | @@ -90,7 +116,7 @@ module LayoutHelper | ||
90 | end | 116 | end |
91 | 117 | ||
92 | def meta_description_tag(article=nil) | 118 | def meta_description_tag(article=nil) |
93 | - article ? truncate(strip_tags(article.body.to_s), :length => 200) : environment.name | 119 | + article ? CGI.escapeHTML(truncate(strip_tags(article.body.to_s), :length => 200)) : environment.name |
94 | end | 120 | end |
95 | end | 121 | end |
96 | 122 |
app/helpers/person_notifier_helper.rb
app/helpers/profile_helper.rb
1 | module ProfileHelper | 1 | module ProfileHelper |
2 | 2 | ||
3 | - def display_field(title, profile, field, force = false) | 3 | + COMMON_CATEGORIES = ActiveSupport::OrderedHash.new |
4 | + COMMON_CATEGORIES[:content] = [:blogs, :image_galleries, :events, :article_tags] | ||
5 | + COMMON_CATEGORIES[:interests] = [:interests] | ||
6 | + COMMON_CATEGORIES[:general] = nil | ||
7 | + | ||
8 | + PERSON_CATEGORIES = ActiveSupport::OrderedHash.new | ||
9 | + PERSON_CATEGORIES[:basic_information] = [:nickname, :sex, :birth_date, :location, :privacy_setting, :created_at] | ||
10 | + PERSON_CATEGORIES[:contact] = [:contact_phone, :cell_phone, :comercial_phone, :contact_information, :email, :personal_website, :jabber_id] | ||
11 | + PERSON_CATEGORIES[:location] = [:address, :address_reference, :zip_code, :city, :state, :district, :country, :nationality] | ||
12 | + PERSON_CATEGORIES[:work] = [:organization, :organization_website, :professional_activity] | ||
13 | + PERSON_CATEGORIES[:study] = [:schooling, :formation, :area_of_study] | ||
14 | + PERSON_CATEGORIES[:network] = [:friends, :communities, :enterprises] | ||
15 | + PERSON_CATEGORIES.merge!(COMMON_CATEGORIES) | ||
16 | + | ||
17 | + ORGANIZATION_CATEGORIES = ActiveSupport::OrderedHash.new | ||
18 | + ORGANIZATION_CATEGORIES[:basic_information] = [:display_name, :created_at, :foundation_year, :type, :language, :members_count, :location, :address_reference, :historic_and_current_context, :admins] | ||
19 | + ORGANIZATION_CATEGORIES[:contact] = [:contact_person, :contact_phone, :contact_email, :organization_website, :jabber_id] | ||
20 | + ORGANIZATION_CATEGORIES[:economic] = [:business_name, :acronym, :economic_activity, :legal_form, :products, :activities_short_description, :management_information] | ||
21 | + ORGANIZATION_CATEGORIES.merge!(COMMON_CATEGORIES) | ||
22 | + | ||
23 | + CATEGORY_MAP = ActiveSupport::OrderedHash.new | ||
24 | + CATEGORY_MAP[:person] = PERSON_CATEGORIES | ||
25 | + CATEGORY_MAP[:organization] = ORGANIZATION_CATEGORIES | ||
26 | + | ||
27 | + FORCE = { | ||
28 | + :person => [:privacy_setting], | ||
29 | + :organization => [:privacy_setting, :location], | ||
30 | + } | ||
31 | + | ||
32 | + MULTIPLE = { | ||
33 | + :person => [:blogs, :image_galleries, :interests], | ||
34 | + :organization => [:blogs, :image_galleries, :interests], | ||
35 | + } | ||
36 | + | ||
37 | + CUSTOM_LABELS = { | ||
38 | + :zip_code => _('ZIP code'), | ||
39 | + :email => _('e-Mail'), | ||
40 | + :jabber_id => _('Jabber'), | ||
41 | + :birth_date => _('Date of birth'), | ||
42 | + :created_at => _('Profile created at'), | ||
43 | + :members_count => _('Members'), | ||
44 | + :privacy_setting => _('Privacy setting'), | ||
45 | + :article_tags => _('Tags') | ||
46 | + } | ||
47 | + | ||
48 | + EXCEPTION = { | ||
49 | + :person => [:image, :preferred_domain, :description, :tag_list], | ||
50 | + :organization => [:image, :preferred_domain, :description, :tag_list, :address, :zip_code, :city, :state, :country, :district] | ||
51 | + } | ||
52 | + | ||
53 | + def general_fields | ||
54 | + categorized_fields = CATEGORY_MAP[kind].values.flatten | ||
55 | + profile.class.fields.map(&:to_sym) - categorized_fields - EXCEPTION[kind] | ||
56 | + end | ||
57 | + | ||
58 | + def kind | ||
59 | + if profile.kind_of?(Person) | ||
60 | + :person | ||
61 | + else | ||
62 | + :organization | ||
63 | + end | ||
64 | + end | ||
65 | + | ||
66 | + def title(field, entry = nil) | ||
67 | + return self.send("#{field}_custom_title", entry) if MULTIPLE[kind].include?(field) && entry.present? | ||
68 | + CUSTOM_LABELS[field.to_sym] || _(field.to_s.humanize) | ||
69 | + end | ||
70 | + | ||
71 | + def display_field(field) | ||
72 | + force = FORCE[kind].include?(field) | ||
73 | + multiple = MULTIPLE[kind].include?(field) | ||
4 | unless force || profile.may_display_field_to?(field, user) | 74 | unless force || profile.may_display_field_to?(field, user) |
5 | return '' | 75 | return '' |
6 | end | 76 | end |
7 | - value = profile.send(field) | ||
8 | - if !value.blank? | ||
9 | - if block_given? | ||
10 | - value = yield(value) | ||
11 | - end | ||
12 | - content_tag('tr', content_tag('td', title, :class => 'field-name') + content_tag('td', value)) | 77 | + value = begin profile.send(field) rescue nil end |
78 | + return '' if value.blank? | ||
79 | + if value.kind_of?(Hash) | ||
80 | + content = self.send("treat_#{field}", value) | ||
81 | + content_tag('tr', content_tag('td', title(field), :class => 'field-name') + content_tag('td', content)) | ||
13 | else | 82 | else |
14 | - '' | 83 | + entries = multiple ? value : [] << value |
84 | + entries.map do |entry| | ||
85 | + content = self.send("treat_#{field}", entry) | ||
86 | + unless content.blank? | ||
87 | + content_tag('tr', content_tag('td', title(field, entry), :class => 'field-name') + content_tag('td', content)) | ||
88 | + end | ||
89 | + end.join("\n") | ||
15 | end | 90 | end |
16 | end | 91 | end |
17 | 92 | ||
18 | - def display_contact(profile) | ||
19 | - fields = [] | ||
20 | - fields << display_field(_('Address:'), profile, :address).html_safe | ||
21 | - fields << display_field(_('ZIP code:'), profile, :zip_code).html_safe | ||
22 | - fields << display_field(_('Contact phone:'), profile, :contact_phone).html_safe | ||
23 | - fields << display_field(_('e-Mail:'), profile, :email) { |email| link_to_email(email) }.html_safe | ||
24 | - fields << display_field(_('Personal website:'), profile, :personal_website).html_safe | ||
25 | - fields << display_field(_('Jabber:'), profile, :jabber_id).html_safe | ||
26 | - if fields.reject!(&:blank?).empty? | ||
27 | - '' | ||
28 | - else | ||
29 | - content_tag('tr', content_tag('th', _('Contact'), { :colspan => 2 })) + fields.join.html_safe | 93 | + def treat_email(email) |
94 | + link_to_email(email) | ||
95 | + end | ||
96 | + | ||
97 | + def treat_organization_website(url) | ||
98 | + link_to(url, url) | ||
99 | + end | ||
100 | + | ||
101 | + def treat_sex(gender) | ||
102 | + { 'male' => _('Male'), 'female' => _('Female') }[gender] | ||
103 | + end | ||
104 | + | ||
105 | + def treat_date(date) | ||
106 | + show_date(date.to_date) | ||
107 | + end | ||
108 | + alias :treat_birth_date :treat_date | ||
109 | + alias :treat_created_at :treat_date | ||
110 | + | ||
111 | + def treat_friends(friends) | ||
112 | + link_to friends.count, :controller => 'profile', :action => 'friends' | ||
113 | + end | ||
114 | + | ||
115 | + def treat_communities(communities) | ||
116 | + link_to communities.count, :controller => "profile", :action => 'communities' | ||
117 | + end | ||
118 | + | ||
119 | + def treat_enterprises(enterprises) | ||
120 | + if environment.disabled?('disable_asset_enterprises') | ||
121 | + link_to enterprises.count, :controller => "profile", :action => 'enterprises' | ||
122 | + end | ||
123 | + end | ||
124 | + | ||
125 | + def treat_members_count(count) | ||
126 | + link_to count, :controller => 'profile', :action => 'members' | ||
127 | + end | ||
128 | + | ||
129 | + def treat_products(products) | ||
130 | + if profile.kind_of?(Enterprise) && profile.environment.enabled?('products_for_enterprises') | ||
131 | + link_to _('Products/Services'), :controller => 'catalog', :action => 'index' | ||
30 | end | 132 | end |
31 | end | 133 | end |
32 | 134 | ||
33 | - def display_work_info(profile) | ||
34 | - organization = display_field(_('Organization:'), profile, :organization) | ||
35 | - organization_site = display_field(_('Organization website:'), profile, :organization_website) { |url| link_to(url, url) } | ||
36 | - if organization.blank? && organization_site.blank? | ||
37 | - '' | 135 | + def treat_admins(admins) |
136 | + profile.admins.map { |admin| link_to(admin.short_name, admin.url)}.join(', ') | ||
137 | + end | ||
138 | + | ||
139 | + def treat_blogs(blog) | ||
140 | + link_to(n_('One post', '%{num} posts', blog.posts.published.count) % { :num => blog.posts.published.count }, blog.url) | ||
141 | + end | ||
142 | + | ||
143 | + def treat_image_galleries(gallery) | ||
144 | + link_to(n_('One picture', '%{num} pictures', gallery.images.published.count) % { :num => gallery.images.published.count }, gallery.url) | ||
145 | + end | ||
146 | + | ||
147 | + def treat_events(events) | ||
148 | + link_to events.published.count, :controller => 'events', :action => 'events' | ||
149 | + end | ||
150 | + | ||
151 | + def treat_article_tags(tags) | ||
152 | + tag_cloud @tags, :id, { :action => 'tags' }, :max_size => 18, :min_size => 10 | ||
153 | + end | ||
154 | + | ||
155 | + def treat_interests(interest) | ||
156 | + link_to interest.name, :controller => 'search', :action => 'category_index', :category_path => interest.explode_path | ||
157 | + end | ||
158 | + | ||
159 | + def article_custom_title(article) | ||
160 | + article.name | ||
161 | + end | ||
162 | + alias :blogs_custom_title :article_custom_title | ||
163 | + alias :image_galleries_custom_title :article_custom_title | ||
164 | + | ||
165 | + def interests_custom_title(interest) | ||
166 | + '' | ||
167 | + end | ||
168 | + | ||
169 | + def method_missing(method, *args, &block) | ||
170 | + if method.to_s =~ /^treat_(.+)$/ | ||
171 | + args[0] | ||
172 | + elsif method.to_s =~ /^display_(.+)$/ && CATEGORY_MAP[kind].has_key?($1.to_sym) | ||
173 | + category = $1.to_sym | ||
174 | + fields = category == :general ? general_fields : CATEGORY_MAP[kind][category] | ||
175 | + contents = [] | ||
176 | + | ||
177 | + fields.each do |field| | ||
178 | + contents << display_field(field).html_safe | ||
179 | + end | ||
180 | + | ||
181 | + contents = contents.delete_if(&:blank?) | ||
182 | + | ||
183 | + unless contents.empty? | ||
184 | + content_tag('tr', content_tag('th', title(category), { :colspan => 2 })) + contents.join.html_safe | ||
185 | + else | ||
186 | + '' | ||
187 | + end | ||
38 | else | 188 | else |
39 | - content_tag('tr', content_tag('th', _('Work'), { :colspan => 2 })) + organization + organization_site | 189 | + super |
40 | end | 190 | end |
41 | end | 191 | end |
42 | 192 |
app/helpers/role_helper.rb
app/helpers/search_helper.rb
@@ -21,6 +21,12 @@ module SearchHelper | @@ -21,6 +21,12 @@ module SearchHelper | ||
21 | 'more_comments' => _('More comments') | 21 | 'more_comments' => _('More comments') |
22 | } | 22 | } |
23 | 23 | ||
24 | + COMMON_PROFILE_LIST_BLOCK = [ | ||
25 | + :enterprises, | ||
26 | + :people, | ||
27 | + :communities | ||
28 | + ] | ||
29 | + | ||
24 | # FIXME remove it after search_controler refactored | 30 | # FIXME remove it after search_controler refactored |
25 | include EventsHelper | 31 | include EventsHelper |
26 | 32 | ||
@@ -94,7 +100,7 @@ module SearchHelper | @@ -94,7 +100,7 @@ module SearchHelper | ||
94 | compact_link = display?(asset, :compact) ? (display == 'compact' ? _('Compact') : link_to(_('Compact'), params.merge(:display => 'compact'))) : nil | 100 | compact_link = display?(asset, :compact) ? (display == 'compact' ? _('Compact') : link_to(_('Compact'), params.merge(:display => 'compact'))) : nil |
95 | map_link = display?(asset, :map) ? (display == 'map' ? _('Map') : link_to(_('Map'), params.merge(:display => 'map'))) : nil | 101 | map_link = display?(asset, :map) ? (display == 'map' ? _('Map') : link_to(_('Map'), params.merge(:display => 'map'))) : nil |
96 | full_link = display?(asset, :full) ? (display == 'full' ? _('Full') : link_to(_('Full'), params.merge(:display => 'full'))) : nil | 102 | full_link = display?(asset, :full) ? (display == 'full' ? _('Full') : link_to(_('Full'), params.merge(:display => 'full'))) : nil |
97 | - content_tag('div', | 103 | + content_tag('div', |
98 | content_tag('strong', _('Display')) + ': ' + [compact_link, map_link, full_link].compact.join(' | ').html_safe, | 104 | content_tag('strong', _('Display')) + ': ' + [compact_link, map_link, full_link].compact.join(' | ').html_safe, |
99 | :class => 'search-customize-options' | 105 | :class => 'search-customize-options' |
100 | ) | 106 | ) |
app/helpers/sweeper_helper.rb
@@ -56,12 +56,12 @@ module SweeperHelper | @@ -56,12 +56,12 @@ module SweeperHelper | ||
56 | if profile | 56 | if profile |
57 | profile.blocks.each {|block| | 57 | profile.blocks.each {|block| |
58 | conditions = block.class.expire_on | 58 | conditions = block.class.expire_on |
59 | - blocks_to_expire << block unless (conditions[:profile] & causes).empty? | 59 | + blocks_to_expire << block unless (conditions[:profile] & causes).blank? |
60 | } | 60 | } |
61 | end | 61 | end |
62 | environment.blocks.each {|block| | 62 | environment.blocks.each {|block| |
63 | conditions = block.class.expire_on | 63 | conditions = block.class.expire_on |
64 | - blocks_to_expire << block unless (conditions[:environment] & causes).empty? | 64 | + blocks_to_expire << block unless (conditions[:environment] & causes).blank? |
65 | } | 65 | } |
66 | 66 | ||
67 | blocks_to_expire.uniq! | 67 | blocks_to_expire.uniq! |
@@ -0,0 +1,51 @@ | @@ -0,0 +1,51 @@ | ||
1 | +module TinymceHelper | ||
2 | + include MacrosHelper | ||
3 | + | ||
4 | + def tinymce_js | ||
5 | + output = '' | ||
6 | + output += javascript_include_tag 'tinymce/js/tinymce/tinymce.min.js' | ||
7 | + output += javascript_include_tag 'tinymce/js/tinymce/jquery.tinymce.min.js' | ||
8 | + output += javascript_include_tag 'tinymce.js' | ||
9 | + output += include_macro_js_files.to_s | ||
10 | + output | ||
11 | + end | ||
12 | + | ||
13 | + def tinymce_init_js options = {} | ||
14 | + options.merge! :document_base_url => top_url, | ||
15 | + :content_css => "/stylesheets/tinymce.css,#{macro_css_files}", | ||
16 | + :plugins => %w[compat3x advlist autolink lists link image charmap print preview hr anchor pagebreak | ||
17 | + searchreplace wordcount visualblocks visualchars code fullscreen | ||
18 | + insertdatetime media nonbreaking save table contextmenu directionality | ||
19 | + emoticons template paste textcolor colorpicker textpattern], | ||
20 | + :language => tinymce_language | ||
21 | + | ||
22 | + options[:toolbar1] = "insertfile undo redo | copy paste | bold italic underline | styleselect fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image" | ||
23 | + if options[:mode] == 'simple' | ||
24 | + options[:menubar] = false | ||
25 | + else | ||
26 | + options[:menubar] = 'edit insert view tools' | ||
27 | + options[:toolbar2] = 'print preview code media | table' | ||
28 | + | ||
29 | + options[:toolbar2] += ' | macros' | ||
30 | + macros_with_buttons.each do |macro| | ||
31 | + options[:toolbar2] += " #{macro.identifier}" | ||
32 | + end | ||
33 | + end | ||
34 | + | ||
35 | + options[:macros_setup] = macros_with_buttons.map do |macro| | ||
36 | + <<-EOS | ||
37 | + ed.addButton('#{macro.identifier}', { | ||
38 | + title: #{macro_title(macro).to_json}, | ||
39 | + onclick: #{generate_macro_config_dialog macro}, | ||
40 | + image : '#{macro.configuration[:icon_path]}' | ||
41 | + }); | ||
42 | + EOS | ||
43 | + end | ||
44 | + | ||
45 | + #cleanup non tinymce options | ||
46 | + options = options.except :mode | ||
47 | + | ||
48 | + "noosfero.tinymce.init(#{options.to_json})" | ||
49 | + end | ||
50 | + | ||
51 | +end |
app/helpers/token_helper.rb
@@ -18,6 +18,7 @@ module TokenHelper | @@ -18,6 +18,7 @@ module TokenHelper | ||
18 | options[:on_add] ||= 'null' | 18 | options[:on_add] ||= 'null' |
19 | options[:on_delete] ||= 'null' | 19 | options[:on_delete] ||= 'null' |
20 | options[:on_ready] ||= 'null' | 20 | options[:on_ready] ||= 'null' |
21 | + options[:query_param] ||= 'q' | ||
21 | 22 | ||
22 | result = text_field_tag(name, nil, text_field_options.merge(html_options.merge({:id => element_id}))) | 23 | result = text_field_tag(name, nil, text_field_options.merge(html_options.merge({:id => element_id}))) |
23 | result += javascript_tag("jQuery('##{element_id}') | 24 | result += javascript_tag("jQuery('##{element_id}') |
@@ -30,7 +31,7 @@ module TokenHelper | @@ -30,7 +31,7 @@ module TokenHelper | ||
30 | searchDelay: #{options[:search_delay].to_json}, | 31 | searchDelay: #{options[:search_delay].to_json}, |
31 | preventDuplicates: #{options[:prevent_duplicates].to_json}, | 32 | preventDuplicates: #{options[:prevent_duplicates].to_json}, |
32 | backspaceDeleteItem: #{options[:backspace_delete_item].to_json}, | 33 | backspaceDeleteItem: #{options[:backspace_delete_item].to_json}, |
33 | - queryParam: #{name.to_json}, | 34 | + queryParam: #{options[:query_param].to_json}, |
34 | tokenLimit: #{options[:token_limit].to_json}, | 35 | tokenLimit: #{options[:token_limit].to_json}, |
35 | onResult: #{options[:on_result]}, | 36 | onResult: #{options[:on_result]}, |
36 | onAdd: #{options[:on_add]}, | 37 | onAdd: #{options[:on_add]}, |
@@ -48,4 +49,4 @@ module TokenHelper | @@ -48,4 +49,4 @@ module TokenHelper | ||
48 | result | 49 | result |
49 | end | 50 | end |
50 | 51 | ||
51 | -end | ||
52 | \ No newline at end of file | 52 | \ No newline at end of file |
53 | +end |
app/models/article.rb
@@ -2,7 +2,14 @@ require 'hpricot' | @@ -2,7 +2,14 @@ require 'hpricot' | ||
2 | 2 | ||
3 | class Article < ActiveRecord::Base | 3 | class Article < ActiveRecord::Base |
4 | 4 | ||
5 | - attr_accessible :name, :body, :abstract, :profile, :tag_list, :parent, :allow_members_to_edit, :translation_of_id, :language, :license_id, :parent_id, :display_posts_in_current_language, :category_ids, :posts_per_page, :moderate_comments, :accept_comments, :feed, :published, :source, :highlighted, :notify_comments, :display_hits, :slug, :external_feed_builder, :display_versions, :external_link, :image_builder | 5 | + attr_accessible :name, :body, :abstract, :profile, :tag_list, :parent, |
6 | + :allow_members_to_edit, :translation_of_id, :language, | ||
7 | + :license_id, :parent_id, :display_posts_in_current_language, | ||
8 | + :category_ids, :posts_per_page, :moderate_comments, | ||
9 | + :accept_comments, :feed, :published, :source, | ||
10 | + :highlighted, :notify_comments, :display_hits, :slug, | ||
11 | + :external_feed_builder, :display_versions, :external_link, | ||
12 | + :image_builder, :show_to_followers | ||
6 | 13 | ||
7 | acts_as_having_image | 14 | acts_as_having_image |
8 | 15 | ||
@@ -40,6 +47,12 @@ class Article < ActiveRecord::Base | @@ -40,6 +47,12 @@ class Article < ActiveRecord::Base | ||
40 | # xss_terminate plugin can't sanitize array fields | 47 | # xss_terminate plugin can't sanitize array fields |
41 | before_save :sanitize_tag_list | 48 | before_save :sanitize_tag_list |
42 | 49 | ||
50 | + before_create do |article| | ||
51 | + if article.author | ||
52 | + article.author_name = article.author.name | ||
53 | + end | ||
54 | + end | ||
55 | + | ||
43 | belongs_to :profile | 56 | belongs_to :profile |
44 | validates_presence_of :profile_id, :name | 57 | validates_presence_of :profile_id, :name |
45 | validates_presence_of :slug, :path, :if => lambda { |article| !article.name.blank? } | 58 | validates_presence_of :slug, :path, :if => lambda { |article| !article.name.blank? } |
@@ -48,6 +61,7 @@ class Article < ActiveRecord::Base | @@ -48,6 +61,7 @@ class Article < ActiveRecord::Base | ||
48 | 61 | ||
49 | validates_uniqueness_of :slug, :scope => ['profile_id', 'parent_id'], :message => N_('The title (article name) is already being used by another article, please use another title.'), :if => lambda { |article| !article.slug.blank? } | 62 | validates_uniqueness_of :slug, :scope => ['profile_id', 'parent_id'], :message => N_('The title (article name) is already being used by another article, please use another title.'), :if => lambda { |article| !article.slug.blank? } |
50 | 63 | ||
64 | + belongs_to :author, :class_name => 'Person' | ||
51 | belongs_to :last_changed_by, :class_name => 'Person', :foreign_key => 'last_changed_by_id' | 65 | belongs_to :last_changed_by, :class_name => 'Person', :foreign_key => 'last_changed_by_id' |
52 | belongs_to :created_by, :class_name => 'Person', :foreign_key => 'created_by_id' | 66 | belongs_to :created_by, :class_name => 'Person', :foreign_key => 'created_by_id' |
53 | 67 | ||
@@ -155,14 +169,17 @@ class Article < ActiveRecord::Base | @@ -155,14 +169,17 @@ class Article < ActiveRecord::Base | ||
155 | self.profile | 169 | self.profile |
156 | end | 170 | end |
157 | 171 | ||
158 | - def self.human_attribute_name(attrib, options = {}) | 172 | + def self.human_attribute_name_with_customization(attrib, options={}) |
159 | case attrib.to_sym | 173 | case attrib.to_sym |
160 | when :name | 174 | when :name |
161 | _('Title') | 175 | _('Title') |
162 | else | 176 | else |
163 | - _(self.superclass.human_attribute_name(attrib)) | 177 | + _(self.human_attribute_name_without_customization(attrib)) |
164 | end | 178 | end |
165 | end | 179 | end |
180 | + class << self | ||
181 | + alias_method_chain :human_attribute_name, :customization | ||
182 | + end | ||
166 | 183 | ||
167 | def css_class_list | 184 | def css_class_list |
168 | [self.class.name.to_css_class] | 185 | [self.class.name.to_css_class] |
@@ -280,13 +297,6 @@ class Article < ActiveRecord::Base | @@ -280,13 +297,6 @@ class Article < ActiveRecord::Base | ||
280 | end | 297 | end |
281 | end | 298 | end |
282 | 299 | ||
283 | - def reported_version(options = {}) | ||
284 | - article = self | ||
285 | - search_path = Rails.root.join('app', 'views', 'shared', 'reported_versions') | ||
286 | - partial_path = File.join('shared', 'reported_versions', partial_for_class_in_view_path(article.class, search_path)) | ||
287 | - lambda { render_to_string(:partial => partial_path, :locals => {:article => article}) } | ||
288 | - end | ||
289 | - | ||
290 | # returns the data of the article. Must be overriden in each subclass to | 300 | # returns the data of the article. Must be overriden in each subclass to |
291 | # provide the correct content for the article. | 301 | # provide the correct content for the article. |
292 | def data | 302 | def data |
@@ -335,7 +345,7 @@ class Article < ActiveRecord::Base | @@ -335,7 +345,7 @@ class Article < ActiveRecord::Base | ||
335 | def belongs_to_blog? | 345 | def belongs_to_blog? |
336 | self.parent and self.parent.blog? | 346 | self.parent and self.parent.blog? |
337 | end | 347 | end |
338 | - | 348 | + |
339 | def belongs_to_forum? | 349 | def belongs_to_forum? |
340 | self.parent and self.parent.forum? | 350 | self.parent and self.parent.forum? |
341 | end | 351 | end |
@@ -447,6 +457,7 @@ class Article < ActiveRecord::Base | @@ -447,6 +457,7 @@ class Article < ActiveRecord::Base | ||
447 | if self.parent && !self.parent.published? | 457 | if self.parent && !self.parent.published? |
448 | return false | 458 | return false |
449 | end | 459 | end |
460 | + | ||
450 | true | 461 | true |
451 | else | 462 | else |
452 | false | 463 | false |
@@ -461,10 +472,10 @@ class Article < ActiveRecord::Base | @@ -461,10 +472,10 @@ class Article < ActiveRecord::Base | ||
461 | ['TextArticle', 'TextileArticle', 'TinyMceArticle'] | 472 | ['TextArticle', 'TextileArticle', 'TinyMceArticle'] |
462 | end | 473 | end |
463 | 474 | ||
464 | - scope :published, :conditions => { :published => true } | ||
465 | - scope :folders, lambda {|profile|{:conditions => { :type => profile.folder_types} }} | ||
466 | - scope :no_folders, lambda {|profile|{:conditions => ['type NOT IN (?)', profile.folder_types]}} | ||
467 | - scope :galleries, :conditions => { :type => 'Gallery' } | 475 | + scope :published, :conditions => ['articles.published = ?', true] |
476 | + scope :folders, lambda {|profile|{:conditions => ['articles.type IN (?)', profile.folder_types] }} | ||
477 | + scope :no_folders, lambda {|profile|{:conditions => ['articles.type NOT IN (?)', profile.folder_types]}} | ||
478 | + scope :galleries, :conditions => [ "articles.type IN ('Gallery')" ] | ||
468 | scope :images, :conditions => { :is_image => true } | 479 | scope :images, :conditions => { :is_image => true } |
469 | scope :text_articles, :conditions => [ 'articles.type IN (?)', text_article_types ] | 480 | scope :text_articles, :conditions => [ 'articles.type IN (?)', text_article_types ] |
470 | scope :with_types, lambda { |types| { :conditions => [ 'articles.type IN (?)', types ] } } | 481 | scope :with_types, lambda { |types| { :conditions => [ 'articles.type IN (?)', types ] } } |
@@ -474,18 +485,21 @@ class Article < ActiveRecord::Base | @@ -474,18 +485,21 @@ class Article < ActiveRecord::Base | ||
474 | scope :more_recent, :order => "created_at DESC" | 485 | scope :more_recent, :order => "created_at DESC" |
475 | 486 | ||
476 | def self.display_filter(user, profile) | 487 | def self.display_filter(user, profile) |
477 | - return {:conditions => ['published = ?', true]} if !user | 488 | + return {:conditions => ['articles.published = ?', true]} if !user |
478 | {:conditions => [" articles.published = ? OR | 489 | {:conditions => [" articles.published = ? OR |
479 | articles.last_changed_by_id = ? OR | 490 | articles.last_changed_by_id = ? OR |
480 | articles.profile_id = ? OR | 491 | articles.profile_id = ? OR |
481 | - ?", | ||
482 | - true, user.id, user.id, user.has_permission?(:view_private_content, profile)] } | 492 | + ? OR articles.show_to_followers = ? AND ?", |
493 | + true, user.id, user.id, user.has_permission?(:view_private_content, profile), | ||
494 | + true, user.follows?(profile)]} | ||
483 | end | 495 | end |
484 | 496 | ||
497 | + | ||
485 | def display_unpublished_article_to?(user) | 498 | def display_unpublished_article_to?(user) |
486 | user == author || allow_view_private_content?(user) || user == profile || | 499 | user == author || allow_view_private_content?(user) || user == profile || |
487 | user.is_admin?(profile.environment) || user.is_admin?(profile) || | 500 | user.is_admin?(profile.environment) || user.is_admin?(profile) || |
488 | - article_privacy_exceptions.include?(user) | 501 | + article_privacy_exceptions.include?(user) || |
502 | + (self.show_to_followers && user.follows?(profile)) | ||
489 | end | 503 | end |
490 | 504 | ||
491 | def display_to?(user = nil) | 505 | def display_to?(user = nil) |
@@ -501,6 +515,7 @@ class Article < ActiveRecord::Base | @@ -501,6 +515,7 @@ class Article < ActiveRecord::Base | ||
501 | end | 515 | end |
502 | 516 | ||
503 | def allow_post_content?(user = nil) | 517 | def allow_post_content?(user = nil) |
518 | + return true if allow_edit_topic?(user) | ||
504 | user && (user.has_permission?('post_content', profile) || allow_publish_content?(user) && (user == author)) | 519 | user && (user.has_permission?('post_content', profile) || allow_publish_content?(user) && (user == author)) |
505 | end | 520 | end |
506 | 521 | ||
@@ -520,9 +535,14 @@ class Article < ActiveRecord::Base | @@ -520,9 +535,14 @@ class Article < ActiveRecord::Base | ||
520 | end | 535 | end |
521 | 536 | ||
522 | def allow_edit?(user) | 537 | def allow_edit?(user) |
538 | + return true if allow_edit_topic?(user) | ||
523 | allow_post_content?(user) || user && allow_members_to_edit && user.is_member_of?(profile) | 539 | allow_post_content?(user) || user && allow_members_to_edit && user.is_member_of?(profile) |
524 | end | 540 | end |
525 | 541 | ||
542 | + def allow_edit_topic?(user) | ||
543 | + self.belongs_to_forum? && (user == author) && user.present? && user.is_member_of?(profile) | ||
544 | + end | ||
545 | + | ||
526 | def moderate_comments? | 546 | def moderate_comments? |
527 | moderate_comments == true | 547 | moderate_comments == true |
528 | end | 548 | end |
@@ -637,35 +657,36 @@ class Article < ActiveRecord::Base | @@ -637,35 +657,36 @@ class Article < ActiveRecord::Base | ||
637 | can_display_versions? && display_versions | 657 | can_display_versions? && display_versions |
638 | end | 658 | end |
639 | 659 | ||
640 | - def author(version_number = nil) | ||
641 | - if version_number | ||
642 | - version = self.versions.find_by_version(version_number) | ||
643 | - author_id = version.last_changed_by_id if version | ||
644 | - else | ||
645 | - author_id = self.created_by_id | ||
646 | - end | 660 | + def get_version(version_number = nil) |
661 | + version_number ? versions.find(:first, :order => 'version', :offset => version_number - 1) : versions.earliest | ||
662 | + end | ||
647 | 663 | ||
648 | - environment.people.find_by_id(author_id) | 664 | + def author_by_version(version_number = nil) |
665 | + version_number ? profile.environment.people.find_by_id(get_version(version_number).author_id) : author | ||
649 | end | 666 | end |
650 | 667 | ||
651 | def author_name(version_number = nil) | 668 | def author_name(version_number = nil) |
652 | - person = author(version_number) | ||
653 | - person ? person.name : (setting[:author_name] || _('Unknown')) | 669 | + person = author_by_version(version_number) |
670 | + if version_number | ||
671 | + person ? person.name : _('Unknown') | ||
672 | + else | ||
673 | + person ? person.name : (setting[:author_name] || _('Unknown')) | ||
674 | + end | ||
654 | end | 675 | end |
655 | 676 | ||
656 | def author_url(version_number = nil) | 677 | def author_url(version_number = nil) |
657 | - person = author(version_number) | 678 | + person = author_by_version(version_number) |
658 | person ? person.url : nil | 679 | person ? person.url : nil |
659 | end | 680 | end |
660 | 681 | ||
661 | def author_id(version_number = nil) | 682 | def author_id(version_number = nil) |
662 | - person = author(version_number) | 683 | + person = author_by_version(version_number) |
663 | person ? person.id : nil | 684 | person ? person.id : nil |
664 | end | 685 | end |
665 | 686 | ||
666 | def version_license(version_number = nil) | 687 | def version_license(version_number = nil) |
667 | return license if version_number.nil? | 688 | return license if version_number.nil? |
668 | - profile.environment.licenses.find_by_id(versions.find_by_version(version_number).license_id) | 689 | + profile.environment.licenses.find_by_id(get_version(version_number).license_id) |
669 | end | 690 | end |
670 | 691 | ||
671 | alias :active_record_cache_key :cache_key | 692 | alias :active_record_cache_key :cache_key |
app/models/block.rb
1 | class Block < ActiveRecord::Base | 1 | class Block < ActiveRecord::Base |
2 | 2 | ||
3 | - attr_accessible :title, :display, :limit, :box_id, :posts_per_page, :visualization_format, :language, :display_user, :box | 3 | + attr_accessible :title, :display, :limit, :box_id, :posts_per_page, :visualization_format, :language, :display_user, :box, :fixed |
4 | 4 | ||
5 | # to be able to generate HTML | 5 | # to be able to generate HTML |
6 | include ActionView::Helpers::UrlHelper | 6 | include ActionView::Helpers::UrlHelper |
@@ -64,7 +64,7 @@ class Block < ActiveRecord::Base | @@ -64,7 +64,7 @@ class Block < ActiveRecord::Base | ||
64 | end | 64 | end |
65 | 65 | ||
66 | def display_to_user?(user) | 66 | def display_to_user?(user) |
67 | - display_user == 'all' || (user.nil? && display_user == 'not_logged') || (user && display_user == 'logged') | 67 | + display_user == 'all' || (user.nil? && display_user == 'not_logged') || (user && display_user == 'logged') || (user && display_user == 'followers' && user.follows?(owner)) |
68 | end | 68 | end |
69 | 69 | ||
70 | def display_always(context) | 70 | def display_always(context) |
@@ -75,7 +75,7 @@ class Block < ActiveRecord::Base | @@ -75,7 +75,7 @@ class Block < ActiveRecord::Base | ||
75 | if context[:article] | 75 | if context[:article] |
76 | return context[:article] == owner.home_page | 76 | return context[:article] == owner.home_page |
77 | else | 77 | else |
78 | - return context[:request_path] == '/' | 78 | + return home_page_path?(context[:request_path]) |
79 | end | 79 | end |
80 | end | 80 | end |
81 | 81 | ||
@@ -83,7 +83,7 @@ class Block < ActiveRecord::Base | @@ -83,7 +83,7 @@ class Block < ActiveRecord::Base | ||
83 | if context[:article] | 83 | if context[:article] |
84 | return context[:article] != owner.home_page | 84 | return context[:article] != owner.home_page |
85 | else | 85 | else |
86 | - return context[:request_path] != '/' + (owner.kind_of?(Profile) ? owner.identifier : '') | 86 | + return !home_page_path?(context[:request_path]) |
87 | end | 87 | end |
88 | end | 88 | end |
89 | 89 | ||
@@ -110,11 +110,14 @@ class Block < ActiveRecord::Base | @@ -110,11 +110,14 @@ class Block < ActiveRecord::Base | ||
110 | # * <tt>'all'</tt>: the block is always displayed | 110 | # * <tt>'all'</tt>: the block is always displayed |
111 | settings_items :language, :type => :string, :default => 'all' | 111 | settings_items :language, :type => :string, :default => 'all' |
112 | 112 | ||
113 | + # The block can be configured to be fixed. Only can be edited by environment admins | ||
114 | + settings_items :fixed, :type => :boolean, :default => false | ||
115 | + | ||
113 | # returns the description of the block, used when the user sees a list of | 116 | # returns the description of the block, used when the user sees a list of |
114 | # blocks to choose one to include in the design. | 117 | # blocks to choose one to include in the design. |
115 | # | 118 | # |
116 | # Must be redefined in subclasses to match the description of each block | 119 | # Must be redefined in subclasses to match the description of each block |
117 | - # type. | 120 | + # type. |
118 | def self.description | 121 | def self.description |
119 | '(dummy)' | 122 | '(dummy)' |
120 | end | 123 | end |
@@ -124,13 +127,13 @@ class Block < ActiveRecord::Base | @@ -124,13 +127,13 @@ class Block < ActiveRecord::Base | ||
124 | # This method can return several types of objects: | 127 | # This method can return several types of objects: |
125 | # | 128 | # |
126 | # * <tt>String</tt>: if the string starts with <tt>http://</tt> or <tt>https://</tt>, then it is assumed to be address of an IFRAME. Otherwise it's is used as regular HTML. | 129 | # * <tt>String</tt>: if the string starts with <tt>http://</tt> or <tt>https://</tt>, then it is assumed to be address of an IFRAME. Otherwise it's is used as regular HTML. |
127 | - # * <tt>Hash</tt>: the hash is used to build an URL that is used as the address for a IFRAME. | 130 | + # * <tt>Hash</tt>: the hash is used to build an URL that is used as the address for a IFRAME. |
128 | # * <tt>Proc</tt>: the Proc is evaluated in the scope of BoxesHelper. The | 131 | # * <tt>Proc</tt>: the Proc is evaluated in the scope of BoxesHelper. The |
129 | # block can then use <tt>render</tt>, <tt>link_to</tt>, etc. | 132 | # block can then use <tt>render</tt>, <tt>link_to</tt>, etc. |
130 | # | 133 | # |
131 | # The method can also return <tt>nil</tt>, which means "no content". | 134 | # The method can also return <tt>nil</tt>, which means "no content". |
132 | # | 135 | # |
133 | - # See BoxesHelper#extract_block_content for implementation details. | 136 | + # See BoxesHelper#extract_block_content for implementation details. |
134 | def content(args={}) | 137 | def content(args={}) |
135 | "This is block number %d" % self.id | 138 | "This is block number %d" % self.id |
136 | end | 139 | end |
@@ -192,7 +195,7 @@ class Block < ActiveRecord::Base | @@ -192,7 +195,7 @@ class Block < ActiveRecord::Base | ||
192 | 195 | ||
193 | # Override in your subclasses. | 196 | # Override in your subclasses. |
194 | # Define which events and context should cause the block cache to expire | 197 | # Define which events and context should cause the block cache to expire |
195 | - # Possible events are: :article, :profile, :friendship, :category | 198 | + # Possible events are: :article, :profile, :friendship, :category, :role_assignment |
196 | # Possible contexts are: :profile, :environment | 199 | # Possible contexts are: :profile, :environment |
197 | def self.expire_on | 200 | def self.expire_on |
198 | { | 201 | { |
@@ -221,6 +224,7 @@ class Block < ActiveRecord::Base | @@ -221,6 +224,7 @@ class Block < ActiveRecord::Base | ||
221 | 'all' => _('All users'), | 224 | 'all' => _('All users'), |
222 | 'logged' => _('Logged'), | 225 | 'logged' => _('Logged'), |
223 | 'not_logged' => _('Not logged'), | 226 | 'not_logged' => _('Not logged'), |
227 | + 'followers' => owner.class != Environment && owner.organization? ? _('Members') : _('Friends') | ||
224 | } | 228 | } |
225 | end | 229 | end |
226 | 230 | ||
@@ -234,4 +238,26 @@ class Block < ActiveRecord::Base | @@ -234,4 +238,26 @@ class Block < ActiveRecord::Base | ||
234 | duplicated_block | 238 | duplicated_block |
235 | end | 239 | end |
236 | 240 | ||
241 | + def copy_from(block) | ||
242 | + self.settings = block.settings | ||
243 | + self.position = block.position | ||
244 | + end | ||
245 | + | ||
246 | + private | ||
247 | + | ||
248 | + def home_page_path | ||
249 | + home_page_url = Noosfero.root('/') | ||
250 | + | ||
251 | + if owner.kind_of?(Profile) | ||
252 | + home_page_url += "profile/" if owner.home_page.nil? | ||
253 | + home_page_url += owner.identifier | ||
254 | + end | ||
255 | + | ||
256 | + return home_page_url | ||
257 | + end | ||
258 | + | ||
259 | + def home_page_path? path | ||
260 | + return path == home_page_path || path == (home_page_path + '/') | ||
261 | + end | ||
262 | + | ||
237 | end | 263 | end |
app/models/blog.rb
@@ -53,7 +53,7 @@ class Blog < Folder | @@ -53,7 +53,7 @@ class Blog < Folder | ||
53 | def prepare_external_feed | 53 | def prepare_external_feed |
54 | unless self.external_feed_data.nil? | 54 | unless self.external_feed_data.nil? |
55 | if self.external_feed(true) && self.external_feed.id == self.external_feed_data[:id].to_i | 55 | if self.external_feed(true) && self.external_feed.id == self.external_feed_data[:id].to_i |
56 | - self.external_feed.attributes = self.external_feed_data | 56 | + self.external_feed.attributes = self.external_feed_data.except(:id) |
57 | else | 57 | else |
58 | self.build_external_feed(self.external_feed_data, :without_protection => true) | 58 | self.build_external_feed(self.external_feed_data, :without_protection => true) |
59 | end | 59 | end |
app/models/box.rb
@@ -28,9 +28,6 @@ class Box < ActiveRecord::Base | @@ -28,9 +28,6 @@ class Box < ActiveRecord::Base | ||
28 | CategoriesBlock, | 28 | CategoriesBlock, |
29 | CommunitiesBlock, | 29 | CommunitiesBlock, |
30 | EnterprisesBlock, | 30 | EnterprisesBlock, |
31 | - # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from | ||
32 | - # the Noosfero core soon, see ActionItem3045 | ||
33 | - EnvironmentStatisticsBlock, | ||
34 | FansBlock, | 31 | FansBlock, |
35 | FavoriteEnterprisesBlock, | 32 | FavoriteEnterprisesBlock, |
36 | FeedReaderBlock, | 33 | FeedReaderBlock, |
@@ -53,9 +50,6 @@ class Box < ActiveRecord::Base | @@ -53,9 +50,6 @@ class Box < ActiveRecord::Base | ||
53 | CommunitiesBlock, | 50 | CommunitiesBlock, |
54 | DisabledEnterpriseMessageBlock, | 51 | DisabledEnterpriseMessageBlock, |
55 | EnterprisesBlock, | 52 | EnterprisesBlock, |
56 | - # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from | ||
57 | - # the Noosfero core soon, see ActionItem3045 | ||
58 | - EnvironmentStatisticsBlock, | ||
59 | FansBlock, | 53 | FansBlock, |
60 | FavoriteEnterprisesBlock, | 54 | FavoriteEnterprisesBlock, |
61 | FeaturedProductsBlock, | 55 | FeaturedProductsBlock, |
app/models/category.rb
@@ -14,9 +14,6 @@ class Category < ActiveRecord::Base | @@ -14,9 +14,6 @@ class Category < ActiveRecord::Base | ||
14 | validates_uniqueness_of :slug,:scope => [ :environment_id, :parent_id ], :message => N_('{fn} is already being used by another category.').fix_i18n | 14 | validates_uniqueness_of :slug,:scope => [ :environment_id, :parent_id ], :message => N_('{fn} is already being used by another category.').fix_i18n |
15 | belongs_to :environment | 15 | belongs_to :environment |
16 | 16 | ||
17 | - validates_inclusion_of :display_color, :in => 1..15, :allow_nil => true | ||
18 | - validates_uniqueness_of :display_color, :scope => :environment_id, :if => (lambda { |cat| ! cat.display_color.nil? }), :message => N_('{fn} was already assigned to another category.').fix_i18n | ||
19 | - | ||
20 | # Finds all top level categories for a given environment. | 17 | # Finds all top level categories for a given environment. |
21 | scope :top_level_for, lambda { |environment| | 18 | scope :top_level_for, lambda { |environment| |
22 | {:conditions => ['parent_id is null and environment_id = ?', environment.id ]} | 19 | {:conditions => ['parent_id is null and environment_id = ?', environment.id ]} |
@@ -42,6 +39,13 @@ class Category < ActiveRecord::Base | @@ -42,6 +39,13 @@ class Category < ActiveRecord::Base | ||
42 | 39 | ||
43 | acts_as_having_image | 40 | acts_as_having_image |
44 | 41 | ||
42 | + before_save :normalize_display_color | ||
43 | + | ||
44 | + def normalize_display_color | ||
45 | + display_color.gsub!('#', '') if display_color | ||
46 | + display_color = nil if display_color.blank? | ||
47 | + end | ||
48 | + | ||
45 | scope :from_types, lambda { |types| | 49 | scope :from_types, lambda { |types| |
46 | types.select{ |t| t.blank? }.empty? ? | 50 | types.select{ |t| t.blank? }.empty? ? |
47 | { :conditions => { :type => types } } : | 51 | { :conditions => { :type => types } } : |
@@ -101,4 +105,12 @@ class Category < ActiveRecord::Base | @@ -101,4 +105,12 @@ class Category < ActiveRecord::Base | ||
101 | self.children.find(:all, :conditions => {:display_in_menu => true}).empty? | 105 | self.children.find(:all, :conditions => {:display_in_menu => true}).empty? |
102 | end | 106 | end |
103 | 107 | ||
108 | + def with_color | ||
109 | + if display_color.blank? | ||
110 | + parent.nil? ? nil : parent.with_color | ||
111 | + else | ||
112 | + self | ||
113 | + end | ||
114 | + end | ||
115 | + | ||
104 | end | 116 | end |
app/models/change_password.rb
@@ -2,16 +2,19 @@ class ChangePassword < Task | @@ -2,16 +2,19 @@ class ChangePassword < Task | ||
2 | 2 | ||
3 | attr_accessor :password, :password_confirmation | 3 | attr_accessor :password, :password_confirmation |
4 | 4 | ||
5 | - def self.human_attribute_name(attrib, options = {}) | 5 | + def self.human_attribute_name_with_customization(attrib, options={}) |
6 | case attrib.to_sym | 6 | case attrib.to_sym |
7 | when :password | 7 | when :password |
8 | _('Password') | 8 | _('Password') |
9 | when :password_confirmation | 9 | when :password_confirmation |
10 | _('Password Confirmation') | 10 | _('Password Confirmation') |
11 | else | 11 | else |
12 | - _(self.superclass.human_attribute_name(attrib)) | 12 | + _(self.human_attribute_name_without_customization(attrib)) |
13 | end | 13 | end |
14 | end | 14 | end |
15 | + class << self | ||
16 | + alias_method_chain :human_attribute_name, :customization | ||
17 | + end | ||
15 | 18 | ||
16 | validates_presence_of :requestor | 19 | validates_presence_of :requestor |
17 | 20 |
app/models/comment.rb
@@ -109,14 +109,17 @@ class Comment < ActiveRecord::Base | @@ -109,14 +109,17 @@ class Comment < ActiveRecord::Base | ||
109 | include Noosfero::Plugin::HotSpot | 109 | include Noosfero::Plugin::HotSpot |
110 | 110 | ||
111 | include Spammable | 111 | include Spammable |
112 | + include CacheCounterHelper | ||
112 | 113 | ||
113 | def after_spam! | 114 | def after_spam! |
114 | SpammerLogger.log(ip_address, self) | 115 | SpammerLogger.log(ip_address, self) |
115 | Delayed::Job.enqueue(CommentHandler.new(self.id, :marked_as_spam)) | 116 | Delayed::Job.enqueue(CommentHandler.new(self.id, :marked_as_spam)) |
117 | + update_cache_counter(:spam_comments_count, source, 1) if source.kind_of?(Article) | ||
116 | end | 118 | end |
117 | 119 | ||
118 | def after_ham! | 120 | def after_ham! |
119 | Delayed::Job.enqueue(CommentHandler.new(self.id, :marked_as_ham)) | 121 | Delayed::Job.enqueue(CommentHandler.new(self.id, :marked_as_ham)) |
122 | + update_cache_counter(:spam_comments_count, source, -1) if source.kind_of?(Article) | ||
120 | end | 123 | end |
121 | 124 | ||
122 | def verify_and_notify | 125 | def verify_and_notify |
app/models/community.rb
@@ -50,16 +50,6 @@ class Community < Organization | @@ -50,16 +50,6 @@ class Community < Organization | ||
50 | super + FIELDS | 50 | super + FIELDS |
51 | end | 51 | end |
52 | 52 | ||
53 | - validate :presence_of_required_fieds | ||
54 | - | ||
55 | - def presence_of_required_fieds | ||
56 | - self.required_fields.each do |field| | ||
57 | - if self.send(field).blank? | ||
58 | - self.errors.add_on_blank(field) | ||
59 | - end | ||
60 | - end | ||
61 | - end | ||
62 | - | ||
63 | def active_fields | 53 | def active_fields |
64 | environment ? environment.active_community_fields : [] | 54 | environment ? environment.active_community_fields : [] |
65 | end | 55 | end |
@@ -78,7 +68,7 @@ class Community < Organization | @@ -78,7 +68,7 @@ class Community < Organization | ||
78 | end | 68 | end |
79 | 69 | ||
80 | def default_template | 70 | def default_template |
81 | - environment.community_template | 71 | + environment.community_default_template |
82 | end | 72 | end |
83 | 73 | ||
84 | def news(limit = 30, highlight = false) | 74 | def news(limit = 30, highlight = false) |
app/models/domain.rb
@@ -2,7 +2,7 @@ require 'noosfero/multi_tenancy' | @@ -2,7 +2,7 @@ require 'noosfero/multi_tenancy' | ||
2 | 2 | ||
3 | class Domain < ActiveRecord::Base | 3 | class Domain < ActiveRecord::Base |
4 | 4 | ||
5 | - attr_accessible :name, :owner | 5 | + attr_accessible :name, :owner, :is_default |
6 | 6 | ||
7 | # relationships | 7 | # relationships |
8 | ############### | 8 | ############### |
@@ -92,4 +92,11 @@ class Domain < ActiveRecord::Base | @@ -92,4 +92,11 @@ class Domain < ActiveRecord::Base | ||
92 | @hosting = {} | 92 | @hosting = {} |
93 | end | 93 | end |
94 | 94 | ||
95 | + # Detects a domain's custom text domain chain if available based on a domain | ||
96 | + # served on multitenancy configuration or a registered domain. | ||
97 | + def self.custom_locale(domainname) | ||
98 | + domain = Noosfero::MultiTenancy.mapping[domainname] || domainname[/(.*?)\./,1] | ||
99 | + FastGettext.translation_repositories.keys.include?(domain) ? domain : FastGettext.default_text_domain | ||
100 | + end | ||
101 | + | ||
95 | end | 102 | end |
app/models/enterprise.rb
@@ -25,7 +25,10 @@ class Enterprise < Organization | @@ -25,7 +25,10 @@ class Enterprise < Organization | ||
25 | N_('Organization website'); N_('Historic and current context'); N_('Activities short description'); N_('City'); N_('State'); N_('Country'); N_('ZIP code') | 25 | N_('Organization website'); N_('Historic and current context'); N_('Activities short description'); N_('City'); N_('State'); N_('Country'); N_('ZIP code') |
26 | 26 | ||
27 | settings_items :organization_website, :historic_and_current_context, :activities_short_description | 27 | settings_items :organization_website, :historic_and_current_context, :activities_short_description |
28 | + | ||
28 | settings_items :products_per_catalog_page, :type => :integer, :default => 6 | 29 | settings_items :products_per_catalog_page, :type => :integer, :default => 6 |
30 | + alias_method :products_per_catalog_page_before_type_cast, :products_per_catalog_page | ||
31 | + validates_numericality_of :products_per_catalog_page, :allow_nil => true, :greater_than => 0 | ||
29 | 32 | ||
30 | extend SetProfileRegionFromCityState::ClassMethods | 33 | extend SetProfileRegionFromCityState::ClassMethods |
31 | set_profile_region_from_city_state | 34 | set_profile_region_from_city_state |
@@ -56,16 +59,6 @@ class Enterprise < Organization | @@ -56,16 +59,6 @@ class Enterprise < Organization | ||
56 | super + FIELDS | 59 | super + FIELDS |
57 | end | 60 | end |
58 | 61 | ||
59 | - validate :presence_of_required_fieds | ||
60 | - | ||
61 | - def presence_of_required_fieds | ||
62 | - self.required_fields.each do |field| | ||
63 | - if self.send(field).blank? | ||
64 | - self.errors.add_on_blank(field) | ||
65 | - end | ||
66 | - end | ||
67 | - end | ||
68 | - | ||
69 | def active_fields | 62 | def active_fields |
70 | environment ? environment.active_enterprise_fields : [] | 63 | environment ? environment.active_enterprise_fields : [] |
71 | end | 64 | end |
@@ -104,7 +97,12 @@ class Enterprise < Organization | @@ -104,7 +97,12 @@ class Enterprise < Organization | ||
104 | self.tasks.where(:type => 'EnterpriseActivation').first | 97 | self.tasks.where(:type => 'EnterpriseActivation').first |
105 | end | 98 | end |
106 | 99 | ||
107 | - def enable(owner) | 100 | + def enable(owner = nil) |
101 | + if owner.nil? | ||
102 | + self.visible = true | ||
103 | + return self.save | ||
104 | + end | ||
105 | + | ||
108 | return if enabled | 106 | return if enabled |
109 | # must be set first for the following to work | 107 | # must be set first for the following to work |
110 | self.enabled = true | 108 | self.enabled = true |
@@ -166,7 +164,7 @@ class Enterprise < Organization | @@ -166,7 +164,7 @@ class Enterprise < Organization | ||
166 | end | 164 | end |
167 | 165 | ||
168 | def default_template | 166 | def default_template |
169 | - environment.enterprise_template | 167 | + environment.enterprise_default_template |
170 | end | 168 | end |
171 | 169 | ||
172 | def template_with_inactive_enterprise | 170 | def template_with_inactive_enterprise |
app/models/environment.rb
@@ -3,7 +3,7 @@ | @@ -3,7 +3,7 @@ | ||
3 | # domains. | 3 | # domains. |
4 | class Environment < ActiveRecord::Base | 4 | class Environment < ActiveRecord::Base |
5 | 5 | ||
6 | - attr_accessible :name, :is_default, :signup_welcome_text_subject, :signup_welcome_text_body, :terms_of_use, :message_for_disabled_enterprise, :news_amount_by_folder, :default_language, :languages, :description, :organization_approval_method, :enabled_plugins, :enabled_features, :redirection_after_login, :redirection_after_signup, :contact_email, :theme, :reports_lower_bound, :noreply_email, :signup_welcome_screen_body | 6 | + attr_accessible :name, :is_default, :signup_welcome_text_subject, :signup_welcome_text_body, :terms_of_use, :message_for_disabled_enterprise, :news_amount_by_folder, :default_language, :languages, :description, :organization_approval_method, :enabled_plugins, :enabled_features, :redirection_after_login, :redirection_after_signup, :contact_email, :theme, :reports_lower_bound, :noreply_email, :signup_welcome_screen_body, :members_whitelist_enabled, :members_whitelist |
7 | 7 | ||
8 | has_many :users | 8 | has_many :users |
9 | 9 | ||
@@ -124,6 +124,7 @@ class Environment < ActiveRecord::Base | @@ -124,6 +124,7 @@ class Environment < ActiveRecord::Base | ||
124 | 'organizations_are_moderated_by_default' => _("Organizations have moderated publication by default"), | 124 | 'organizations_are_moderated_by_default' => _("Organizations have moderated publication by default"), |
125 | 'enable_organization_url_change' => _("Allow organizations to change their URL"), | 125 | 'enable_organization_url_change' => _("Allow organizations to change their URL"), |
126 | 'admin_must_approve_new_communities' => _("Admin must approve creation of communities"), | 126 | 'admin_must_approve_new_communities' => _("Admin must approve creation of communities"), |
127 | + 'admin_must_approve_new_users' => _("Admin must approve registration of new users"), | ||
127 | 'show_balloon_with_profile_links_when_clicked' => _('Show a balloon with profile links when a profile image is clicked'), | 128 | 'show_balloon_with_profile_links_when_clicked' => _('Show a balloon with profile links when a profile image is clicked'), |
128 | 'xmpp_chat' => _('XMPP/Jabber based chat'), | 129 | 'xmpp_chat' => _('XMPP/Jabber based chat'), |
129 | 'show_zoom_button_on_article_images' => _('Show a zoom link on all article images'), | 130 | 'show_zoom_button_on_article_images' => _('Show a zoom link on all article images'), |
@@ -132,7 +133,8 @@ class Environment < ActiveRecord::Base | @@ -132,7 +133,8 @@ class Environment < ActiveRecord::Base | ||
132 | 'send_welcome_email_to_new_users' => _('Send welcome e-mail to new users'), | 133 | 'send_welcome_email_to_new_users' => _('Send welcome e-mail to new users'), |
133 | 'allow_change_of_redirection_after_login' => _('Allow users to set the page to redirect after login'), | 134 | 'allow_change_of_redirection_after_login' => _('Allow users to set the page to redirect after login'), |
134 | 'display_my_communities_on_user_menu' => _('Display on menu the list of communities the user can manage'), | 135 | 'display_my_communities_on_user_menu' => _('Display on menu the list of communities the user can manage'), |
135 | - 'display_my_enterprises_on_user_menu' => _('Display on menu the list of enterprises the user can manage') | 136 | + 'display_my_enterprises_on_user_menu' => _('Display on menu the list of enterprises the user can manage'), |
137 | + 'restrict_to_members' => _('Show content only to members') | ||
136 | } | 138 | } |
137 | end | 139 | end |
138 | 140 | ||
@@ -175,9 +177,6 @@ class Environment < ActiveRecord::Base | @@ -175,9 +177,6 @@ class Environment < ActiveRecord::Base | ||
175 | 177 | ||
176 | # "left" area | 178 | # "left" area |
177 | env.boxes[1].blocks << LoginBlock.new | 179 | env.boxes[1].blocks << LoginBlock.new |
178 | - # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from | ||
179 | - # the Noosfero core soon, see ActionItem3045 | ||
180 | - env.boxes[1].blocks << EnvironmentStatisticsBlock.new | ||
181 | env.boxes[1].blocks << RecentDocumentsBlock.new | 180 | env.boxes[1].blocks << RecentDocumentsBlock.new |
182 | 181 | ||
183 | # "right" area | 182 | # "right" area |
@@ -284,6 +283,7 @@ class Environment < ActiveRecord::Base | @@ -284,6 +283,7 @@ class Environment < ActiveRecord::Base | ||
284 | www.flickr.com | 283 | www.flickr.com |
285 | www.gmodules.com | 284 | www.gmodules.com |
286 | www.youtube.com | 285 | www.youtube.com |
286 | + openstreetmap.org | ||
287 | ] + ('a' .. 'z').map{|i| "#{i}.yimg.com"} | 287 | ] + ('a' .. 'z').map{|i| "#{i}.yimg.com"} |
288 | 288 | ||
289 | settings_items :enabled_plugins, :type => Array, :default => Noosfero::Plugin.available_plugin_names | 289 | settings_items :enabled_plugins, :type => Array, :default => Noosfero::Plugin.available_plugin_names |
@@ -303,6 +303,17 @@ class Environment < ActiveRecord::Base | @@ -303,6 +303,17 @@ class Environment < ActiveRecord::Base | ||
303 | settings[:signup_welcome_screen_body].present? | 303 | settings[:signup_welcome_screen_body].present? |
304 | end | 304 | end |
305 | 305 | ||
306 | + settings_items :members_whitelist_enabled, :type => :boolean, :default => false | ||
307 | + settings_items :members_whitelist, :type => Array, :default => [] | ||
308 | + | ||
309 | + def in_whitelist?(person) | ||
310 | + !members_whitelist_enabled || members_whitelist.include?(person.id) | ||
311 | + end | ||
312 | + | ||
313 | + def members_whitelist=(members) | ||
314 | + settings[:members_whitelist] = members.split(',').map(&:to_i) | ||
315 | + end | ||
316 | + | ||
306 | def news_amount_by_folder=(amount) | 317 | def news_amount_by_folder=(amount) |
307 | settings[:news_amount_by_folder] = amount.to_i | 318 | settings[:news_amount_by_folder] = amount.to_i |
308 | end | 319 | end |
@@ -646,10 +657,11 @@ class Environment < ActiveRecord::Base | @@ -646,10 +657,11 @@ class Environment < ActiveRecord::Base | ||
646 | { :controller => 'admin_panel', :action => 'index' } | 657 | { :controller => 'admin_panel', :action => 'index' } |
647 | end | 658 | end |
648 | 659 | ||
649 | - def top_url | ||
650 | - url = 'http://' | 660 | + def top_url(scheme = 'http') |
661 | + url = scheme + '://' | ||
651 | url << (Noosfero.url_options.key?(:host) ? Noosfero.url_options[:host] : default_hostname) | 662 | url << (Noosfero.url_options.key?(:host) ? Noosfero.url_options[:host] : default_hostname) |
652 | url << ':' << Noosfero.url_options[:port].to_s if Noosfero.url_options.key?(:port) | 663 | url << ':' << Noosfero.url_options[:port].to_s if Noosfero.url_options.key?(:port) |
664 | + url << Noosfero.root('') | ||
653 | url | 665 | url |
654 | end | 666 | end |
655 | 667 | ||
@@ -717,31 +729,50 @@ class Environment < ActiveRecord::Base | @@ -717,31 +729,50 @@ class Environment < ActiveRecord::Base | ||
717 | ] | 729 | ] |
718 | end | 730 | end |
719 | 731 | ||
720 | - def community_template | 732 | + def is_default_template?(template) |
733 | + is_default = template == community_default_template | ||
734 | + is_default = is_default || template == person_default_template | ||
735 | + is_default = is_default || template == enterprise_default_template | ||
736 | + is_default | ||
737 | + end | ||
738 | + | ||
739 | + def community_templates | ||
740 | + self.communities.templates | ||
741 | + end | ||
742 | + | ||
743 | + def community_default_template | ||
721 | template = Community.find_by_id settings[:community_template_id] | 744 | template = Community.find_by_id settings[:community_template_id] |
722 | - template if template && template.is_template | 745 | + template if template && template.is_template? |
746 | + end | ||
747 | + | ||
748 | + def community_default_template=(value) | ||
749 | + settings[:community_template_id] = value.kind_of?(Community) ? value.id : value | ||
723 | end | 750 | end |
724 | 751 | ||
725 | - def community_template=(value) | ||
726 | - settings[:community_template_id] = value.id | 752 | + def person_templates |
753 | + self.people.templates | ||
727 | end | 754 | end |
728 | 755 | ||
729 | - def person_template | 756 | + def person_default_template |
730 | template = Person.find_by_id settings[:person_template_id] | 757 | template = Person.find_by_id settings[:person_template_id] |
731 | - template if template && template.is_template | 758 | + template if template && template.is_template? |
732 | end | 759 | end |
733 | 760 | ||
734 | - def person_template=(value) | ||
735 | - settings[:person_template_id] = value.id | 761 | + def person_default_template=(value) |
762 | + settings[:person_template_id] = value.kind_of?(Person) ? value.id : value | ||
736 | end | 763 | end |
737 | 764 | ||
738 | - def enterprise_template | 765 | + def enterprise_templates |
766 | + self.enterprises.templates | ||
767 | + end | ||
768 | + | ||
769 | + def enterprise_default_template | ||
739 | template = Enterprise.find_by_id settings[:enterprise_template_id] | 770 | template = Enterprise.find_by_id settings[:enterprise_template_id] |
740 | - template if template && template.is_template | 771 | + template if template && template.is_template? |
741 | end | 772 | end |
742 | 773 | ||
743 | - def enterprise_template=(value) | ||
744 | - settings[:enterprise_template_id] = value.id | 774 | + def enterprise_default_template=(value) |
775 | + settings[:enterprise_template_id] = value.kind_of?(Enterprise) ? value.id : value | ||
745 | end | 776 | end |
746 | 777 | ||
747 | def inactive_enterprise_template | 778 | def inactive_enterprise_template |
@@ -794,7 +825,7 @@ class Environment < ActiveRecord::Base | @@ -794,7 +825,7 @@ class Environment < ActiveRecord::Base | ||
794 | end | 825 | end |
795 | 826 | ||
796 | def notification_emails | 827 | def notification_emails |
797 | - [noreply_email.blank? ? nil : noreply_email].compact + admins.map(&:email) | 828 | + [contact_email].select(&:present?) + admins.map(&:email) |
798 | end | 829 | end |
799 | 830 | ||
800 | after_create :create_templates | 831 | after_create :create_templates |
@@ -839,10 +870,10 @@ class Environment < ActiveRecord::Base | @@ -839,10 +870,10 @@ class Environment < ActiveRecord::Base | ||
839 | person_template.visible = false | 870 | person_template.visible = false |
840 | person_template.save! | 871 | person_template.save! |
841 | 872 | ||
842 | - self.enterprise_template = enterprise_template | 873 | + self.enterprise_default_template = enterprise_template |
843 | self.inactive_enterprise_template = inactive_enterprise_template | 874 | self.inactive_enterprise_template = inactive_enterprise_template |
844 | - self.community_template = community_template | ||
845 | - self.person_template = person_template | 875 | + self.community_default_template = community_template |
876 | + self.person_default_template = person_template | ||
846 | self.save! | 877 | self.save! |
847 | end | 878 | end |
848 | 879 | ||
@@ -906,6 +937,10 @@ class Environment < ActiveRecord::Base | @@ -906,6 +937,10 @@ class Environment < ActiveRecord::Base | ||
906 | locales_list | 937 | locales_list |
907 | end | 938 | end |
908 | 939 | ||
940 | + def has_license? | ||
941 | + self.licenses.any? | ||
942 | + end | ||
943 | + | ||
909 | private | 944 | private |
910 | 945 | ||
911 | def default_language_available | 946 | def default_language_available |
app/models/environment_statistics_block.rb
@@ -1,33 +0,0 @@ | @@ -1,33 +0,0 @@ | ||
1 | -# TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from | ||
2 | -# the Noosfero core soon, see ActionItem3045 | ||
3 | - | ||
4 | -class EnvironmentStatisticsBlock < Block | ||
5 | - | ||
6 | - def self.description | ||
7 | - _('Environment stastistics (DEPRECATED)') | ||
8 | - end | ||
9 | - | ||
10 | - def default_title | ||
11 | - _('Statistics for %s') % owner.name | ||
12 | - end | ||
13 | - | ||
14 | - def help | ||
15 | - _('This block presents some statistics about your environment.') | ||
16 | - end | ||
17 | - | ||
18 | - def content(args={}) | ||
19 | - users = owner.people.visible.count | ||
20 | - enterprises = owner.enterprises.visible.count | ||
21 | - communities = owner.communities.visible.count | ||
22 | - | ||
23 | - info = [] | ||
24 | - info << (n_('One user', '%{num} users', users) % { :num => users }) | ||
25 | - unless owner.enabled?('disable_asset_enterprises') | ||
26 | - info << (n_('One enterprise', '%{num} enterprises', enterprises) % { :num => enterprises }) | ||
27 | - end | ||
28 | - info << (n_('One community', '%{num} communities', communities) % { :num => communities }) | ||
29 | - | ||
30 | - block_title(title) + content_tag('ul', info.map {|item| content_tag('li', item) }.join("\n")) | ||
31 | - end | ||
32 | - | ||
33 | -end |
app/models/event.rb
@@ -19,7 +19,7 @@ class Event < Article | @@ -19,7 +19,7 @@ class Event < Article | ||
19 | maybe_add_http(self.setting[:link]) | 19 | maybe_add_http(self.setting[:link]) |
20 | end | 20 | end |
21 | 21 | ||
22 | - xss_terminate :only => [ :body, :link, :address ], :with => 'white_list', :on => 'validation' | 22 | + xss_terminate :only => [ :name, :body, :link, :address ], :with => 'white_list', :on => 'validation' |
23 | 23 | ||
24 | def initialize(*args) | 24 | def initialize(*args) |
25 | super(*args) | 25 | super(*args) |
app/models/external_feed.rb
@@ -10,9 +10,10 @@ class ExternalFeed < ActiveRecord::Base | @@ -10,9 +10,10 @@ class ExternalFeed < ActiveRecord::Base | ||
10 | { :conditions => ['(fetched_at is NULL) OR (fetched_at < ?)', Time.now - FeedUpdater.update_interval] } | 10 | { :conditions => ['(fetched_at is NULL) OR (fetched_at < ?)', Time.now - FeedUpdater.update_interval] } |
11 | } | 11 | } |
12 | 12 | ||
13 | - attr_accessible :address, :enabled | 13 | + attr_accessible :address, :enabled, :only_once |
14 | 14 | ||
15 | def add_item(title, link, date, content) | 15 | def add_item(title, link, date, content) |
16 | + return if content.blank? | ||
16 | doc = Hpricot(content) | 17 | doc = Hpricot(content) |
17 | doc.search('*').each do |p| | 18 | doc.search('*').each do |p| |
18 | if p.instance_of? Hpricot::Elem | 19 | if p.instance_of? Hpricot::Elem |
@@ -30,6 +31,7 @@ class ExternalFeed < ActiveRecord::Base | @@ -30,6 +31,7 @@ class ExternalFeed < ActiveRecord::Base | ||
30 | article.source = link | 31 | article.source = link |
31 | article.profile = blog.profile | 32 | article.profile = blog.profile |
32 | article.parent = blog | 33 | article.parent = blog |
34 | + article.author_name = self.feed_title | ||
33 | unless blog.children.exists?(:slug => article.slug) | 35 | unless blog.children.exists?(:slug => article.slug) |
34 | article.save! | 36 | article.save! |
35 | article.delay.create_activity | 37 | article.delay.create_activity |
app/models/featured_products_block.rb
1 | class FeaturedProductsBlock < Block | 1 | class FeaturedProductsBlock < Block |
2 | 2 | ||
3 | + attr_accessible :product_ids, :groups_of, :speed, :reflect | ||
4 | + | ||
3 | settings_items :product_ids, :type => Array, :default => [] | 5 | settings_items :product_ids, :type => Array, :default => [] |
4 | settings_items :groups_of, :type => :integer, :default => 3 | 6 | settings_items :groups_of, :type => :integer, :default => 3 |
5 | settings_items :speed, :type => :integer, :default => 1000 | 7 | settings_items :speed, :type => :integer, :default => 1000 |
app/models/feed_reader_block.rb
app/models/folder.rb
@@ -12,7 +12,7 @@ class Folder < Article | @@ -12,7 +12,7 @@ class Folder < Article | ||
12 | 12 | ||
13 | acts_as_having_settings :field => :setting | 13 | acts_as_having_settings :field => :setting |
14 | 14 | ||
15 | - xss_terminate :only => [ :body ], :with => 'white_list', :on => 'validation' | 15 | + xss_terminate :only => [ :name, :body ], :with => 'white_list', :on => 'validation' |
16 | 16 | ||
17 | include WhiteListFilter | 17 | include WhiteListFilter |
18 | filter_iframes :body | 18 | filter_iframes :body |
app/models/highlights_block.rb
1 | class HighlightsBlock < Block | 1 | class HighlightsBlock < Block |
2 | 2 | ||
3 | - attr_accessible :images | 3 | + attr_accessible :images, :interval, :shuffle, :navigation |
4 | 4 | ||
5 | settings_items :images, :type => Array, :default => [] | 5 | settings_items :images, :type => Array, :default => [] |
6 | settings_items :interval, :type => 'integer', :default => 4 | 6 | settings_items :interval, :type => 'integer', :default => 4 |
app/models/invitation.rb
@@ -65,18 +65,16 @@ class Invitation < Task | @@ -65,18 +65,16 @@ class Invitation < Task | ||
65 | 65 | ||
66 | task_args = if user.nil? | 66 | task_args = if user.nil? |
67 | {:person => person, :friend_name => friend_name, :friend_email => friend_email, :message => message} | 67 | {:person => person, :friend_name => friend_name, :friend_email => friend_email, :message => message} |
68 | - elsif !user.person.is_a_friend?(person) | 68 | + else |
69 | {:person => person, :target => user.person} | 69 | {:person => person, :target => user.person} |
70 | end | 70 | end |
71 | 71 | ||
72 | - if !task_args.nil? | ||
73 | - if profile.person? | ||
74 | - InviteFriend.create(task_args) | ||
75 | - elsif profile.community? | ||
76 | - InviteMember.create(task_args.merge(:community_id => profile.id)) | ||
77 | - else | ||
78 | - raise NotImplementedError, 'Don\'t know how to invite people to a %s' % profile.class.to_s | ||
79 | - end | 72 | + if profile.person? |
73 | + InviteFriend.create(task_args) if user.nil? || !user.person.is_a_friend?(person) | ||
74 | + elsif profile.community? | ||
75 | + InviteMember.create(task_args.merge(:community_id => profile.id)) if user.nil? || !user.person.is_member_of?(profile) | ||
76 | + else | ||
77 | + raise NotImplementedError, 'Don\'t know how to invite people to a %s' % profile.class.to_s | ||
80 | end | 78 | end |
81 | end | 79 | end |
82 | end | 80 | end |
app/models/link_list_block.rb
@@ -78,16 +78,17 @@ class LinkListBlock < Block | @@ -78,16 +78,17 @@ class LinkListBlock < Block | ||
78 | address | 78 | address |
79 | end | 79 | end |
80 | if add !~ /^[a-z]+:\/\// && add !~ /^\// | 80 | if add !~ /^[a-z]+:\/\// && add !~ /^\// |
81 | - 'http://' + add | 81 | + '//' + add |
82 | else | 82 | else |
83 | + if root = Noosfero.root | ||
84 | + if !add.starts_with?(root) | ||
85 | + add = root + add | ||
86 | + end | ||
87 | + end | ||
83 | add | 88 | add |
84 | end | 89 | end |
85 | end | 90 | end |
86 | 91 | ||
87 | - def editable? | ||
88 | - true | ||
89 | - end | ||
90 | - | ||
91 | def icons_options | 92 | def icons_options |
92 | ICONS.map do |i| | 93 | ICONS.map do |i| |
93 | "<span title=\"#{i[1]}\" class=\"icon-#{i[0]}\" onclick=\"changeIcon(this, '#{i[0]}')\"></span>".html_safe | 94 | "<span title=\"#{i[1]}\" class=\"icon-#{i[0]}\" onclick=\"changeIcon(this, '#{i[0]}')\"></span>".html_safe |
@@ -100,4 +101,5 @@ class LinkListBlock < Block | @@ -100,4 +101,5 @@ class LinkListBlock < Block | ||
100 | sanitizer = HTML::WhiteListSanitizer.new | 101 | sanitizer = HTML::WhiteListSanitizer.new |
101 | sanitizer.sanitize(text) | 102 | sanitizer.sanitize(text) |
102 | end | 103 | end |
104 | + | ||
103 | end | 105 | end |
app/models/location_block.rb
1 | class LocationBlock < Block | 1 | class LocationBlock < Block |
2 | 2 | ||
3 | + attr_accessible :zoom, :map_type | ||
4 | + | ||
3 | settings_items :zoom, :type => :integer, :default => 4 | 5 | settings_items :zoom, :type => :integer, :default => 4 |
4 | settings_items :map_type, :type => :string, :default => 'roadmap' | 6 | settings_items :map_type, :type => :string, :default => 'roadmap' |
5 | 7 |
app/models/main_block.rb
@@ -0,0 +1,59 @@ | @@ -0,0 +1,59 @@ | ||
1 | +class ModerateUserRegistration < Task | ||
2 | + | ||
3 | + settings_items :user_id, :type => String | ||
4 | + settings_items :name, :type => String | ||
5 | + settings_items :author_name, :type => String | ||
6 | + settings_items :email, :type => String | ||
7 | + | ||
8 | + after_create :schedule_spam_checking | ||
9 | + | ||
10 | + alias :environment :target | ||
11 | + alias :environment= :target= | ||
12 | + | ||
13 | + def schedule_spam_checking | ||
14 | + self.delay.check_for_spam | ||
15 | + end | ||
16 | + | ||
17 | + include Noosfero::Plugin::HotSpot | ||
18 | + | ||
19 | + def sender | ||
20 | + "#{name} (#{email})" | ||
21 | + end | ||
22 | + | ||
23 | + def perform | ||
24 | + user=environment.users.find_by_id(user_id) | ||
25 | + user.activate | ||
26 | + end | ||
27 | + | ||
28 | + def title | ||
29 | + _("New user") | ||
30 | + end | ||
31 | + | ||
32 | + def subject | ||
33 | + name | ||
34 | + end | ||
35 | + | ||
36 | + def information | ||
37 | + { :message => _('%{sender} wants to register.'), | ||
38 | + :variables => {:sender => sender} } | ||
39 | + end | ||
40 | + | ||
41 | + def icon | ||
42 | + result = {:type => :defined_image, :src => '/images/icons-app/person-minor.png', :name => name} | ||
43 | + end | ||
44 | + | ||
45 | + def target_notification_description | ||
46 | + _('%{sender} tried to register.') % | ||
47 | + {:sender => sender} | ||
48 | + end | ||
49 | + | ||
50 | + def target_notification_message | ||
51 | + target_notification_description + "\n\n" + | ||
52 | + _('You need to login on %{system} in order to approve or reject this user.') % { :environment => self.environment } | ||
53 | + end | ||
54 | + | ||
55 | + def target_notification_message | ||
56 | + _("User \"%{user}\" just requested to register. You have to approve or reject it through the \"Pending Validations\" section in your control panel.\n") % { :user => self.name } | ||
57 | + end | ||
58 | + | ||
59 | +end | ||
0 | \ No newline at end of file | 60 | \ No newline at end of file |
app/models/organization.rb
@@ -30,6 +30,16 @@ class Organization < Profile | @@ -30,6 +30,16 @@ class Organization < Profile | ||
30 | 30 | ||
31 | scope :more_popular, :order => 'members_count DESC' | 31 | scope :more_popular, :order => 'members_count DESC' |
32 | 32 | ||
33 | + validate :presence_of_required_fieds, :unless => :is_template | ||
34 | + | ||
35 | + def presence_of_required_fieds | ||
36 | + self.required_fields.each do |field| | ||
37 | + if self.send(field).blank? | ||
38 | + self.errors.add_on_blank(field) | ||
39 | + end | ||
40 | + end | ||
41 | + end | ||
42 | + | ||
33 | def validation_methodology | 43 | def validation_methodology |
34 | self.validation_info ? self.validation_info.validation_methodology : nil | 44 | self.validation_info ? self.validation_info.validation_methodology : nil |
35 | end | 45 | end |
@@ -135,7 +145,11 @@ class Organization < Profile | @@ -135,7 +145,11 @@ class Organization < Profile | ||
135 | end | 145 | end |
136 | 146 | ||
137 | def notification_emails | 147 | def notification_emails |
138 | - [contact_email.blank? ? nil : contact_email].compact + admins.map(&:email) | 148 | + emails = [contact_email].select(&:present?) + admins.map(&:email) |
149 | + if emails.empty? | ||
150 | + emails << environment.contact_email | ||
151 | + end | ||
152 | + emails | ||
139 | end | 153 | end |
140 | 154 | ||
141 | def already_request_membership?(person) | 155 | def already_request_membership?(person) |
app/models/person.rb
@@ -21,6 +21,12 @@ class Person < Profile | @@ -21,6 +21,12 @@ class Person < Profile | ||
21 | { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => [conditions] } | 21 | { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => [conditions] } |
22 | } | 22 | } |
23 | 23 | ||
24 | + scope :by_role, lambda { |roles| | ||
25 | + roles = [roles] unless roles.kind_of?(Array) | ||
26 | + { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => ['role_assignments.role_id IN (?)', | ||
27 | +roles] } | ||
28 | + } | ||
29 | + | ||
24 | def has_permission_with_plugins?(permission, profile) | 30 | def has_permission_with_plugins?(permission, profile) |
25 | permissions = [has_permission_without_plugins?(permission, profile)] | 31 | permissions = [has_permission_without_plugins?(permission, profile)] |
26 | permissions += plugins.map do |plugin| | 32 | permissions += plugins.map do |plugin| |
@@ -74,6 +80,10 @@ class Person < Profile | @@ -74,6 +80,10 @@ class Person < Profile | ||
74 | 80 | ||
75 | belongs_to :user, :dependent => :delete | 81 | belongs_to :user, :dependent => :delete |
76 | 82 | ||
83 | + def can_change_homepage? | ||
84 | + !environment.enabled?('cant_change_homepage') || is_admin? | ||
85 | + end | ||
86 | + | ||
77 | def can_control_scrap?(scrap) | 87 | def can_control_scrap?(scrap) |
78 | begin | 88 | begin |
79 | !self.scraps(scrap).nil? | 89 | !self.scraps(scrap).nil? |
@@ -161,7 +171,7 @@ class Person < Profile | @@ -161,7 +171,7 @@ class Person < Profile | ||
161 | FIELDS | 171 | FIELDS |
162 | end | 172 | end |
163 | 173 | ||
164 | - validate :presence_of_required_fields | 174 | + validate :presence_of_required_fields, :unless => :is_template |
165 | 175 | ||
166 | def presence_of_required_fields | 176 | def presence_of_required_fields |
167 | self.required_fields.each do |field| | 177 | self.required_fields.each do |field| |
@@ -300,7 +310,7 @@ class Person < Profile | @@ -300,7 +310,7 @@ class Person < Profile | ||
300 | end | 310 | end |
301 | 311 | ||
302 | def default_template | 312 | def default_template |
303 | - environment.person_template | 313 | + environment.person_default_template |
304 | end | 314 | end |
305 | 315 | ||
306 | def apply_type_specific_template(template) | 316 | def apply_type_specific_template(template) |
app/models/person_notifier.rb
@@ -67,7 +67,7 @@ class PersonNotifier | @@ -67,7 +67,7 @@ class PersonNotifier | ||
67 | 67 | ||
68 | class Mailer < ActionMailer::Base | 68 | class Mailer < ActionMailer::Base |
69 | 69 | ||
70 | - add_template_helper(PersonNotifierHelper) | 70 | + add_template_helper(ApplicationHelper) |
71 | 71 | ||
72 | def session | 72 | def session |
73 | {:theme => nil} | 73 | {:theme => nil} |
app/models/product.rb
@@ -11,7 +11,7 @@ class Product < ActiveRecord::Base | @@ -11,7 +11,7 @@ class Product < ActiveRecord::Base | ||
11 | 11 | ||
12 | SEARCH_DISPLAYS = %w[map full] | 12 | SEARCH_DISPLAYS = %w[map full] |
13 | 13 | ||
14 | - attr_accessible :name, :product_category, :highlighted, :price, :enterprise, :image_builder, :description, :available, :qualifiers, :unit_id, :discount, :inputs | 14 | + attr_accessible :name, :product_category, :highlighted, :price, :enterprise, :image_builder, :description, :available, :qualifiers, :unit_id, :discount, :inputs, :qualifiers_list |
15 | 15 | ||
16 | def self.default_search_display | 16 | def self.default_search_display |
17 | 'full' | 17 | 'full' |
app/models/product_categories_block.rb
@@ -33,7 +33,7 @@ class ProductCategoriesBlock < Block | @@ -33,7 +33,7 @@ class ProductCategoriesBlock < Block | ||
33 | end | 33 | end |
34 | end | 34 | end |
35 | 35 | ||
36 | - DISPLAY_OPTIONS['catalog_only'] = _('Only on the catalog') | 36 | + DISPLAY_OPTIONS = DISPLAY_OPTIONS.merge('catalog_only' => _('Only on the catalog')) |
37 | 37 | ||
38 | def display | 38 | def display |
39 | settings[:display].nil? ? 'catalog_only' : super | 39 | settings[:display].nil? ? 'catalog_only' : super |
app/models/products_block.rb
@@ -49,17 +49,10 @@ class ProductsBlock < Block | @@ -49,17 +49,10 @@ class ProductsBlock < Block | ||
49 | 49 | ||
50 | def products(reload = false) | 50 | def products(reload = false) |
51 | if product_ids.blank? | 51 | if product_ids.blank? |
52 | - products_list = owner.products(reload) | ||
53 | - result = [] | ||
54 | - [4, products_list.size].min.times do | ||
55 | - p = products_list.sample | ||
56 | - result << p | ||
57 | - products_list -= [p] | ||
58 | - end | ||
59 | - result | 52 | + owner.products.order('RANDOM()').limit([4,owner.products.count].min) |
60 | else | 53 | else |
61 | - product_ids.map {|item| owner.products.find(item) } | ||
62 | - end | 54 | + owner.products.where(:id => product_ids) |
55 | + end.compact | ||
63 | end | 56 | end |
64 | 57 | ||
65 | end | 58 | end |
app/models/profile.rb
@@ -97,7 +97,7 @@ class Profile < ActiveRecord::Base | @@ -97,7 +97,7 @@ class Profile < ActiveRecord::Base | ||
97 | end | 97 | end |
98 | 98 | ||
99 | def members_by_name | 99 | def members_by_name |
100 | - members.order(:name) | 100 | + members.order('profiles.name') |
101 | end | 101 | end |
102 | 102 | ||
103 | class << self | 103 | class << self |
@@ -108,8 +108,8 @@ class Profile < ActiveRecord::Base | @@ -108,8 +108,8 @@ class Profile < ActiveRecord::Base | ||
108 | alias_method_chain :count, :distinct | 108 | alias_method_chain :count, :distinct |
109 | end | 109 | end |
110 | 110 | ||
111 | - def members_by_role(role) | ||
112 | - Person.members_of(self).all(:conditions => ['role_assignments.role_id = ?', role.id]) | 111 | + def members_by_role(roles) |
112 | + Person.members_of(self).by_role(roles) | ||
113 | end | 113 | end |
114 | 114 | ||
115 | acts_as_having_boxes | 115 | acts_as_having_boxes |
@@ -121,7 +121,9 @@ class Profile < ActiveRecord::Base | @@ -121,7 +121,9 @@ class Profile < ActiveRecord::Base | ||
121 | end | 121 | end |
122 | 122 | ||
123 | scope :visible, :conditions => { :visible => true } | 123 | scope :visible, :conditions => { :visible => true } |
124 | + scope :disabled, :conditions => { :visible => false } | ||
124 | scope :public, :conditions => { :visible => true, :public_profile => true } | 125 | scope :public, :conditions => { :visible => true, :public_profile => true } |
126 | + scope :enabled, :conditions => { :enabled => true } | ||
125 | 127 | ||
126 | # Subclasses must override this method | 128 | # Subclasses must override this method |
127 | scope :more_popular | 129 | scope :more_popular |
@@ -346,16 +348,17 @@ class Profile < ActiveRecord::Base | @@ -346,16 +348,17 @@ class Profile < ActiveRecord::Base | ||
346 | end | 348 | end |
347 | 349 | ||
348 | def copy_blocks_from(profile) | 350 | def copy_blocks_from(profile) |
351 | + template_boxes = profile.boxes.select{|box| box.position} | ||
349 | self.boxes.destroy_all | 352 | self.boxes.destroy_all |
350 | - profile.boxes.each do |box| | ||
351 | - new_box = Box.new | 353 | + self.boxes = template_boxes.size.times.map { Box.new } |
354 | + | ||
355 | + template_boxes.each_with_index do |box, i| | ||
356 | + new_box = self.boxes[i] | ||
352 | new_box.position = box.position | 357 | new_box.position = box.position |
353 | - self.boxes << new_box | ||
354 | box.blocks.each do |block| | 358 | box.blocks.each do |block| |
355 | new_block = block.class.new(:title => block[:title]) | 359 | new_block = block.class.new(:title => block[:title]) |
356 | - new_block.settings = block.settings | ||
357 | - new_block.position = block.position | ||
358 | - self.boxes[-1].blocks << new_block | 360 | + new_block.copy_from(block) |
361 | + new_box.blocks << new_block | ||
359 | end | 362 | end |
360 | end | 363 | end |
361 | end | 364 | end |
@@ -390,7 +393,7 @@ class Profile < ActiveRecord::Base | @@ -390,7 +393,7 @@ class Profile < ActiveRecord::Base | ||
390 | end | 393 | end |
391 | 394 | ||
392 | xss_terminate :only => [ :name, :nickname, :address, :contact_phone, :description ], :on => 'validation' | 395 | xss_terminate :only => [ :name, :nickname, :address, :contact_phone, :description ], :on => 'validation' |
393 | - xss_terminate :only => [ :custom_footer, :custom_header ], :with => 'white_list', :on => 'validation' | 396 | + xss_terminate :only => [ :custom_footer, :custom_header ], :with => 'white_list' |
394 | 397 | ||
395 | include WhiteListFilter | 398 | include WhiteListFilter |
396 | filter_iframes :custom_header, :custom_footer | 399 | filter_iframes :custom_header, :custom_footer |
@@ -774,7 +777,7 @@ private :generate_url, :url_options | @@ -774,7 +777,7 @@ private :generate_url, :url_options | ||
774 | end | 777 | end |
775 | 778 | ||
776 | include Noosfero::Plugin::HotSpot | 779 | include Noosfero::Plugin::HotSpot |
777 | - | 780 | + |
778 | def folder_types | 781 | def folder_types |
779 | types = Article.folder_types | 782 | types = Article.folder_types |
780 | plugins.dispatch(:content_types).each {|type| | 783 | plugins.dispatch(:content_types).each {|type| |
@@ -898,6 +901,13 @@ private :generate_url, :url_options | @@ -898,6 +901,13 @@ private :generate_url, :url_options | ||
898 | end | 901 | end |
899 | 902 | ||
900 | def disable | 903 | def disable |
904 | + self.visible = false | ||
905 | + self.save | ||
906 | + end | ||
907 | + | ||
908 | + def enable | ||
909 | + self.visible = true | ||
910 | + self.save | ||
901 | end | 911 | end |
902 | 912 | ||
903 | def control_panel_settings_button | 913 | def control_panel_settings_button |
app/models/profile_image_block.rb
app/models/profile_info_block.rb
app/models/profile_search_block.rb
app/models/rss_feed.rb
app/models/task.rb
@@ -73,10 +73,6 @@ class Task < ActiveRecord::Base | @@ -73,10 +73,6 @@ class Task < ActiveRecord::Base | ||
73 | end | 73 | end |
74 | end | 74 | end |
75 | 75 | ||
76 | - def self.all_types | ||
77 | - %w[Invitation EnterpriseActivation AddMember Ticket SuggestArticle AddFriend CreateCommunity AbuseComplaint ApproveComment ApproveArticle CreateEnterprise ChangePassword EmailActivation InviteFriend InviteMember] | ||
78 | - end | ||
79 | - | ||
80 | # this method finished the task. It calls #perform, which must be overriden | 76 | # this method finished the task. It calls #perform, which must be overriden |
81 | # by subclasses. At the end a message (as returned by #finish_message) is | 77 | # by subclasses. At the end a message (as returned by #finish_message) is |
82 | # sent to the requestor with #notify_requestor. | 78 | # sent to the requestor with #notify_requestor. |
@@ -254,6 +250,10 @@ class Task < ActiveRecord::Base | @@ -254,6 +250,10 @@ class Task < ActiveRecord::Base | ||
254 | { :conditions => [environment_condition, profile_condition].compact.join(' OR ') } | 250 | { :conditions => [environment_condition, profile_condition].compact.join(' OR ') } |
255 | } | 251 | } |
256 | 252 | ||
253 | + def self.pending_types_for(profile) | ||
254 | + Task.to(profile).pending.select('distinct type').map { |t| [t.class.name, t.title] } | ||
255 | + end | ||
256 | + | ||
257 | def opened? | 257 | def opened? |
258 | status == Task::Status::ACTIVE || status == Task::Status::HIDDEN | 258 | status == Task::Status::ACTIVE || status == Task::Status::HIDDEN |
259 | end | 259 | end |
@@ -285,8 +285,9 @@ class Task < ActiveRecord::Base | @@ -285,8 +285,9 @@ class Task < ActiveRecord::Base | ||
285 | # If | 285 | # If |
286 | def send_notification(action) | 286 | def send_notification(action) |
287 | if sends_email? | 287 | if sends_email? |
288 | - if self.requestor | ||
289 | - TaskMailer.generic_message("task_#{action}", self) | 288 | + if self.requestor && !self.requestor.notification_emails.empty? |
289 | + message = TaskMailer.generic_message("task_#{action}", self) | ||
290 | + message.deliver if message | ||
290 | end | 291 | end |
291 | end | 292 | end |
292 | end | 293 | end |
app/models/user.rb
@@ -5,7 +5,7 @@ require 'user_activation_job' | @@ -5,7 +5,7 @@ require 'user_activation_job' | ||
5 | # Rails generator. | 5 | # Rails generator. |
6 | class User < ActiveRecord::Base | 6 | class User < ActiveRecord::Base |
7 | 7 | ||
8 | - attr_accessible :login, :email, :password, :password_confirmation | 8 | + attr_accessible :login, :email, :password, :password_confirmation, :activated_at |
9 | 9 | ||
10 | N_('Password') | 10 | N_('Password') |
11 | N_('Password confirmation') | 11 | N_('Password confirmation') |
@@ -16,15 +16,18 @@ class User < ActiveRecord::Base | @@ -16,15 +16,18 @@ class User < ActiveRecord::Base | ||
16 | end | 16 | end |
17 | 17 | ||
18 | # FIXME ugly workaround | 18 | # FIXME ugly workaround |
19 | - def self.human_attribute_name(attrib, options={}) | 19 | + def self.human_attribute_name_with_customization(attrib, options={}) |
20 | case attrib.to_sym | 20 | case attrib.to_sym |
21 | when :login | 21 | when :login |
22 | return [_('Username'), _('Email')].join(' / ') | 22 | return [_('Username'), _('Email')].join(' / ') |
23 | when :email | 23 | when :email |
24 | return _('e-Mail') | 24 | return _('e-Mail') |
25 | - else _(self.superclass.human_attribute_name(attrib)) | 25 | + else _(self.human_attribute_name_without_customization(attrib)) |
26 | end | 26 | end |
27 | end | 27 | end |
28 | + class << self | ||
29 | + alias_method_chain :human_attribute_name, :customization | ||
30 | + end | ||
28 | 31 | ||
29 | before_create do |user| | 32 | before_create do |user| |
30 | if user.environment.nil? | 33 | if user.environment.nil? |
@@ -47,8 +50,12 @@ class User < ActiveRecord::Base | @@ -47,8 +50,12 @@ class User < ActiveRecord::Base | ||
47 | 50 | ||
48 | user.person = p | 51 | user.person = p |
49 | end | 52 | end |
50 | - if user.environment.enabled?('skip_new_user_email_confirmation') | ||
51 | - user.activate | 53 | + if user.environment.enabled?('skip_new_user_email_confirmation') |
54 | + if user.environment.enabled?('admin_must_approve_new_users') | ||
55 | + create_moderate_task | ||
56 | + else | ||
57 | + user.activate | ||
58 | + end | ||
52 | end | 59 | end |
53 | end | 60 | end |
54 | after_create :deliver_activation_code | 61 | after_create :deliver_activation_code |
@@ -137,6 +144,15 @@ class User < ActiveRecord::Base | @@ -137,6 +144,15 @@ class User < ActiveRecord::Base | ||
137 | end | 144 | end |
138 | end | 145 | end |
139 | 146 | ||
147 | + def create_moderate_task | ||
148 | + @task = ModerateUserRegistration.new | ||
149 | + @task.user_id = self.id | ||
150 | + @task.name = self.name | ||
151 | + @task.email = self.email | ||
152 | + @task.target = self.environment | ||
153 | + @task.save | ||
154 | + end | ||
155 | + | ||
140 | def activated? | 156 | def activated? |
141 | self.activation_code.nil? && !self.activated_at.nil? | 157 | self.activation_code.nil? && !self.activated_at.nil? |
142 | end | 158 | end |
@@ -185,6 +201,10 @@ class User < ActiveRecord::Base | @@ -185,6 +201,10 @@ class User < ActiveRecord::Base | ||
185 | Digest::MD5.hexdigest(password) | 201 | Digest::MD5.hexdigest(password) |
186 | end | 202 | end |
187 | 203 | ||
204 | + add_encryption_method :salted_md5 do |password, salt| | ||
205 | + Digest::MD5.hexdigest(password+salt) | ||
206 | + end | ||
207 | + | ||
188 | add_encryption_method :clear do |password, salt| | 208 | add_encryption_method :clear do |password, salt| |
189 | password | 209 | password |
190 | end | 210 | end |
@@ -334,6 +354,7 @@ class User < ActiveRecord::Base | @@ -334,6 +354,7 @@ class User < ActiveRecord::Base | ||
334 | end | 354 | end |
335 | 355 | ||
336 | def delay_activation_check | 356 | def delay_activation_check |
357 | + return if person.is_template? | ||
337 | Delayed::Job.enqueue(UserActivationJob.new(self.id), {:priority => 0, :run_at => 72.hours.from_now}) | 358 | Delayed::Job.enqueue(UserActivationJob.new(self.id), {:priority => 0, :run_at => 72.hours.from_now}) |
338 | end | 359 | end |
339 | end | 360 | end |
app/presenters/image.rb
@@ -11,4 +11,9 @@ class FilePresenter::Image < FilePresenter | @@ -11,4 +11,9 @@ class FilePresenter::Image < FilePresenter | ||
11 | def short_description | 11 | def short_description |
12 | _('Image (%s)') % content_type.split('/')[1].upcase | 12 | _('Image (%s)') % content_type.split('/')[1].upcase |
13 | end | 13 | end |
14 | + | ||
15 | + #Overwriting method from FilePresenter to allow download of images | ||
16 | + def download?(view = nil) | ||
17 | + view.blank? || view == 'false' | ||
18 | + end | ||
14 | end | 19 | end |
app/sweepers/profile_sweeper.rb
@@ -8,9 +8,6 @@ class ProfileSweeper # < ActiveRecord::Observer | @@ -8,9 +8,6 @@ class ProfileSweeper # < ActiveRecord::Observer | ||
8 | end | 8 | end |
9 | 9 | ||
10 | def after_create(profile) | 10 | def after_create(profile) |
11 | - # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from | ||
12 | - # the Noosfero core soon, see ActionItem3045 | ||
13 | - expire_statistics_block_cache(profile) | ||
14 | end | 11 | end |
15 | 12 | ||
16 | protected | 13 | protected |
@@ -31,13 +28,6 @@ protected | @@ -31,13 +28,6 @@ protected | ||
31 | expire_blogs(profile) if profile.organization? | 28 | expire_blogs(profile) if profile.organization? |
32 | end | 29 | end |
33 | 30 | ||
34 | - # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from | ||
35 | - # the Noosfero core soon, see ActionItem3045 | ||
36 | - def expire_statistics_block_cache(profile) | ||
37 | - blocks = profile.environment.blocks.select { |b| b.kind_of?(EnvironmentStatisticsBlock) } | ||
38 | - BlockSweeper.expire_blocks(blocks) | ||
39 | - end | ||
40 | - | ||
41 | def expire_blogs(profile) | 31 | def expire_blogs(profile) |
42 | profile.blogs.select{|b| !b.empty?}.each do |blog| | 32 | profile.blogs.select{|b| !b.empty?}.each do |blog| |
43 | pages = blog.posts.count / blog.posts_per_page + 1 | 33 | pages = blog.posts.count / blog.posts_per_page + 1 |
app/sweepers/role_assignment_sweeper.rb
@@ -13,20 +13,22 @@ class RoleAssignmentSweeper < ActiveRecord::Observer | @@ -13,20 +13,22 @@ class RoleAssignmentSweeper < ActiveRecord::Observer | ||
13 | protected | 13 | protected |
14 | 14 | ||
15 | def expire_caches(role_assignment) | 15 | def expire_caches(role_assignment) |
16 | - expire_cache(role_assignment.accessor) | ||
17 | - expire_cache(role_assignment.resource) if role_assignment.resource.respond_to?(:cache_keys) | 16 | + expire_cache(role_assignment.accessor) if role_assignment.accessor.kind_of?(Profile) |
17 | + expire_cache(role_assignment.resource) if role_assignment.resource.kind_of?(Profile) | ||
18 | end | 18 | end |
19 | 19 | ||
20 | def expire_cache(profile) | 20 | def expire_cache(profile) |
21 | per_page = Noosfero::Constants::PROFILE_PER_PAGE | 21 | per_page = Noosfero::Constants::PROFILE_PER_PAGE |
22 | - profile.cache_keys(:per_page => per_page).each { |ck| | ||
23 | - expire_timeout_fragment(ck) | ||
24 | - } | 22 | + |
23 | + profile.cache_keys(:per_page => per_page).each { |ck| expire_timeout_fragment(ck) } | ||
24 | + expire_timeout_fragment(profile.members_cache_key(:per_page => per_page)) | ||
25 | 25 | ||
26 | profile.blocks_to_expire_cache.each { |block| | 26 | profile.blocks_to_expire_cache.each { |block| |
27 | blocks = profile.blocks.select{|b| b.kind_of?(block)} | 27 | blocks = profile.blocks.select{|b| b.kind_of?(block)} |
28 | BlockSweeper.expire_blocks(blocks) | 28 | BlockSweeper.expire_blocks(blocks) |
29 | } | 29 | } |
30 | + | ||
31 | + expire_blocks_cache(profile, [:role_assignment]) | ||
30 | end | 32 | end |
31 | 33 | ||
32 | end | 34 | end |
app/views/account/_signup_form.html.erb
@@ -136,8 +136,6 @@ | @@ -136,8 +136,6 @@ | ||
136 | <script type="text/javascript"> | 136 | <script type="text/javascript"> |
137 | jQuery(function($) { | 137 | jQuery(function($) { |
138 | 138 | ||
139 | - $('#signup-form #user_login').css('width', 335 - $('#signup-domain').outerWidth()); | ||
140 | - | ||
141 | $('#signup-form input[type=text], #signup-form textarea').each(function() { | 139 | $('#signup-form input[type=text], #signup-form textarea').each(function() { |
142 | $(this).bind('blur', function() { | 140 | $(this).bind('blur', function() { |
143 | if ($(this).val() == '') { | 141 | if ($(this).val() == '') { |
app/views/account/signup.html.erb
@@ -2,18 +2,36 @@ | @@ -2,18 +2,36 @@ | ||
2 | <div id='thanks-for-signing'> | 2 | <div id='thanks-for-signing'> |
3 | <% if environment.has_custom_welcome_screen? %> | 3 | <% if environment.has_custom_welcome_screen? %> |
4 | <%= environment.settings[:signup_welcome_screen_body].html_safe %> | 4 | <%= environment.settings[:signup_welcome_screen_body].html_safe %> |
5 | - <% else %> | ||
6 | - <h1><%= _("Welcome to %s!") % environment.name %></h1> | ||
7 | - <h3><%= _("Thanks for signing up, we're thrilled to have you on our social network!") %></h3> | ||
8 | - <p><%= _("Firstly, some tips for getting started:") %></p> | ||
9 | - <h4><%= _("Confirm your account!") %></h4> | 5 | + <% elsif environment.enabled?('admin_must_approve_new_users')%> |
6 | + <h1><%= _("Welcome to %s!") % environment.name %></h1> | ||
7 | + <h3><%= _("Thanks for signing up, we're thrilled to have you on our social network!") %></h3> | ||
8 | + <p><%= _("Firstly, some tips for getting started:") %></p> | ||
9 | + <% unless environment.enabled?('skip_new_user_email_confirmation') %> | ||
10 | + <h4><%= _("Confirm your account and wait for admin approvement!") %></h4> | ||
10 | <p><%= _("You should receive a welcome email from us shortly. Please take a second to follow the link within to confirm your account.") %></p> | 11 | <p><%= _("You should receive a welcome email from us shortly. Please take a second to follow the link within to confirm your account.") %></p> |
11 | - <p><%= _("You won't appear as %s until your account is confirmed.") % link_to(_('user'), {:controller => :search, :action => :people, :filter => 'more_recent'}, :target => '_blank') %></p> | ||
12 | - <h4><%= _("What to do next?") %></h4> | ||
13 | - <p><%= _("%s. Upload an avatar and let your friends find you easily :)") % link_to(_('Customize your profile'), {:controller => 'doc', :section => 'user', :topic => 'editing-person-info'}, :target => '_blank') %></p> | ||
14 | - <p><%= _("Learn the guidelines. Read the %s for more details on how to use this social network!") % link_to(_('Documentation'), {:controller => 'doc'}, :target => '_blank') %></p> | ||
15 | - <p><%= _("%s your Gmail, Yahoo and Hotmail contacts!") % link_to(_('Invite and find'), {:controller => 'doc', :section => 'user', :topic => 'invite-contacts'}, :target => '_blank') %></p> | ||
16 | - <p><%= _("Start exploring and have fun!") %></p> | 12 | + <p><%= _("You won't appear as %s until your account is confirmed and approved.") % link_to(_('user'), {:controller => :search, :action => :people, :filter => 'more_recent'}, :target => '_blank') %></p> |
13 | + <% else %> | ||
14 | + <h4><%= _("Wait for admin approvement!") %></h4> | ||
15 | + <p><%= _("The administrators will evaluate your signup request for approvement.") %></p> | ||
16 | + <p><%= _("You won't appear as %s until your account is approved.") % link_to(_('user'), {:controller => :search, :action => :people, :filter => 'more_recent'}, :target => '_blank') %></p> | ||
17 | + <% end %> | ||
18 | + <h4><%= _("What to do next?") %></h4> | ||
19 | + <p><%= _("%s. Upload an avatar and let your friends find you easily :)") % link_to(_('Customize your profile'), {:controller => 'doc', :section => 'user', :topic => 'editing-person-info'}, :target => '_blank') %></p> | ||
20 | + <p><%= _("Learn the guidelines. Read the %s for more details on how to use this social network!") % link_to(_('Documentation'), {:controller => 'doc'}, :target => '_blank') %></p> | ||
21 | + <p><%= _("%s your Gmail, Yahoo and Hotmail contacts!") % link_to(_('Invite and find'), {:controller => 'doc', :section => 'user', :topic => 'invite-contacts'}, :target => '_blank') %></p> | ||
22 | + <p><%= _("Start exploring and have fun!") %></p> | ||
23 | + <% else %> | ||
24 | + <h1><%= _("Welcome to %s!") % environment.name %></h1> | ||
25 | + <h3><%= _("Thanks for signing up, we're thrilled to have you on our social network!") %></h3> | ||
26 | + <p><%= _("Firstly, some tips for getting started:") %></p> | ||
27 | + <h4><%= _("Confirm your account!") %></h4> | ||
28 | + <p><%= _("You should receive a welcome email from us shortly. Please take a second to follow the link within to confirm your account.") %></p> | ||
29 | + <p><%= _("You won't appear as %s until your account is confirmed.") % link_to(_('user'), {:controller => :search, :action => :people, :filter => 'more_recent'}, :target => '_blank') %></p> | ||
30 | + <h4><%= _("What to do next?") %></h4> | ||
31 | + <p><%= _("%s. Upload an avatar and let your friends find you easily :)") % link_to(_('Customize your profile'), {:controller => 'doc', :section => 'user', :topic => 'editing-person-info'}, :target => '_blank') %></p> | ||
32 | + <p><%= _("Learn the guidelines. Read the %s for more details on how to use this social network!") % link_to(_('Documentation'), {:controller => 'doc'}, :target => '_blank') %></p> | ||
33 | + <p><%= _("%s your Gmail, Yahoo and Hotmail contacts!") % link_to(_('Invite and find'), {:controller => 'doc', :section => 'user', :topic => 'invite-contacts'}, :target => '_blank') %></p> | ||
34 | + <p><%= _("Start exploring and have fun!") %></p> | ||
17 | <% end %> | 35 | <% end %> |
18 | </div> | 36 | </div> |
19 | <% else %> | 37 | <% else %> |
app/views/admin_panel/index.html.erb
@@ -20,6 +20,7 @@ | @@ -20,6 +20,7 @@ | ||
20 | <tr><td><%= link_to _('Users'), :controller => 'users' %></td></tr> | 20 | <tr><td><%= link_to _('Users'), :controller => 'users' %></td></tr> |
21 | <tr><td><%= link_to _('Profile templates'), :controller => 'templates' %></td></tr> | 21 | <tr><td><%= link_to _('Profile templates'), :controller => 'templates' %></td></tr> |
22 | <tr><td><%= link_to _('Fields'), :controller => 'features', :action => 'manage_fields' %></td></tr> | 22 | <tr><td><%= link_to _('Fields'), :controller => 'features', :action => 'manage_fields' %></td></tr> |
23 | + <tr><td><%= link_to _('Manage organizations status'), :action => 'manage_organizations_status' %></td></tr> | ||
23 | </table> | 24 | </table> |
24 | 25 | ||
25 | 26 |
app/views/admin_panel/manage_organizations_status.html.erb
0 → 100644
@@ -0,0 +1,69 @@ | @@ -0,0 +1,69 @@ | ||
1 | +<h1><%= _('Manage organizations') %></h1> | ||
2 | + | ||
3 | +<%= form_tag( { :action => 'manage_organizations_status' }, :method => 'get', :class => 'users-search' ) do %> | ||
4 | + | ||
5 | + <div class="search-field"> | ||
6 | + <span class="formfield"> | ||
7 | + <%= text_field_tag 'q', @q, :title => _("Find profiles"), :style=>"width:85%" %> | ||
8 | + </span> | ||
9 | + | ||
10 | + <%= submit_button(:search, _('Search')) %> | ||
11 | + </div> | ||
12 | + | ||
13 | + <div class="environment-users-results-header"> | ||
14 | + <div id='environment-users-filter-title'><%= @title %></div> | ||
15 | + | ||
16 | + <div id="environment-users-filter-filter"> | ||
17 | + <strong><%= _("Filter by: ") %></strong> | ||
18 | + | ||
19 | + <select id="profile_filter_select"> | ||
20 | + <%= options_for_select([['Any', 'any'],["Disabled profiles", "disabled"], ["Enabled profiles", "enabled"]], @filter) %> | ||
21 | + </select> | ||
22 | + </div> | ||
23 | + <div style="clear: both"></div> | ||
24 | + </div> | ||
25 | + | ||
26 | + <table> | ||
27 | + <colgroup> | ||
28 | + <col width="80%"> | ||
29 | + <col width="20%"> | ||
30 | + </colgroup> | ||
31 | + | ||
32 | + <tr> | ||
33 | + <th><%= _('Member') %></th> | ||
34 | + <th><%= _('Actions') %></th> | ||
35 | + </tr> | ||
36 | + | ||
37 | + <% @collection.each do |p| %> | ||
38 | + <tr title="<%= p.name %>"> | ||
39 | + <td><%= link_to_profile p.short_name, p.identifier, :title => p.name %> </td> | ||
40 | + | ||
41 | + <td class='actions'> | ||
42 | + <div class="members-buttons-cell"> | ||
43 | + <% if p.visible %> | ||
44 | + <%= button_without_text :'deactivate-user', _('Deactivate'), {:controller => "profile_editor", :action => 'deactivate_profile', :profile => p.identifier, :id => p.id}, :confirm => _("Do you want to deactivate this profile ?") %> | ||
45 | + <% else %> | ||
46 | + <%= button_without_text :'activate-user', _('Activate'), {:controller => "profile_editor", :action => 'activate_profile', :profile => p.identifier, :id => p.id}, :confirm => _("Do you want to activate this profile ?") %> | ||
47 | + <% end %> | ||
48 | + <%= button_without_text :'delete', _('Remove'), {:controller => "profile_editor", :action => 'destroy_profile', :profile => p.identifier, :id => p.id, :return_to => "/admin/admin_panel/manage_organizations_status"}, :method => :post, :confirm => _("Do you want to deactivate this profile ?") %> | ||
49 | + </div> | ||
50 | + </td> | ||
51 | + </tr> | ||
52 | + <% end %> | ||
53 | + </table> | ||
54 | + | ||
55 | +<% end %> | ||
56 | + | ||
57 | +<%= pagination_links @collection, {:param_name => 'npage', :page_links => true} %> | ||
58 | + | ||
59 | +<% button_bar do %> | ||
60 | + <%= button :back, _('Back'), :controller => 'admin_panel' %> | ||
61 | +<% end %> | ||
62 | + | ||
63 | +<script type="text/javascript"> | ||
64 | + jQuery(document).ready(function(){ | ||
65 | + jQuery("#profile_filter_select").change(function(){ | ||
66 | + document.location.href = '/admin/admin_panel/manage_organizations_status?filter='+this.value; | ||
67 | + }); | ||
68 | + }); | ||
69 | +</script> | ||
0 | \ No newline at end of file | 70 | \ No newline at end of file |
app/views/blocks/my_network.html.erb
1 | <%= block_title(title) %> | 1 | <%= block_title(title) %> |
2 | 2 | ||
3 | -<%= render :file => 'blocks/my_network/' + owner.class.name.underscore, :locals => { :owner => owner } %> | 3 | +<%= render_profile_actions owner.class %> |
4 | 4 | ||
5 | <ul> | 5 | <ul> |
6 | <li><%= link_to(_('Homepage'), owner.url, :class => 'url') %></li> | 6 | <li><%= link_to(_('Homepage'), owner.url, :class => 'url') %></li> |
@@ -11,5 +11,5 @@ | @@ -11,5 +11,5 @@ | ||
11 | </ul> | 11 | </ul> |
12 | 12 | ||
13 | <div class="my-network-actions"> | 13 | <div class="my-network-actions"> |
14 | - <%= render :file => 'blocks/profile_info_actions/' + owner.class.name.underscore %> | 14 | + <%= render 'blocks/profile_info_actions/' + owner.class.name.underscore %> |
15 | </div> | 15 | </div> |
app/views/blocks/profile_image.html.erb
@@ -23,6 +23,6 @@ | @@ -23,6 +23,6 @@ | ||
23 | <% end %> | 23 | <% end %> |
24 | 24 | ||
25 | <div class="profile-info-options"> | 25 | <div class="profile-info-options"> |
26 | - <%= render :file => view_for_profile_actions(block.owner.class) %> | 26 | + <%= render_profile_actions block.owner.class %> |
27 | </div> | 27 | </div> |
28 | </div><!-- end class="vcard" --> | 28 | </div><!-- end class="vcard" --> |
app/views/blocks/profile_info.html.erb
@@ -40,7 +40,7 @@ | @@ -40,7 +40,7 @@ | ||
40 | <% end %> | 40 | <% end %> |
41 | 41 | ||
42 | <div class="profile-info-options"> | 42 | <div class="profile-info-options"> |
43 | - <%= render :file => view_for_profile_actions(block.owner.class) %> | 43 | + <%= render_profile_actions block.owner.class %> |
44 | </div> | 44 | </div> |
45 | 45 | ||
46 | </div><!-- end class="vcard" --> | 46 | </div><!-- end class="vcard" --> |
app/views/blocks/profile_info_actions/_community.html.erb
0 → 100644
@@ -0,0 +1,20 @@ | @@ -0,0 +1,20 @@ | ||
1 | +<ul> | ||
2 | + <li> | ||
3 | + <%= render "blocks/profile_info_actions/join_leave_community" %> | ||
4 | + </li> | ||
5 | + <% if logged_in? %> | ||
6 | + <% if profile.enable_contact? %> | ||
7 | + <li> | ||
8 | + <%= link_to content_tag('span', _('Send an e-mail')), | ||
9 | + { :profile => profile.identifier, | ||
10 | + :controller => 'contact', | ||
11 | + :action => 'new' }, | ||
12 | + {:class => 'button with-text icon-menu-mail', :title => _('Send an e-mail to the administrators')} %> | ||
13 | + </li> | ||
14 | + <% end %> | ||
15 | + | ||
16 | + <li><%= report_abuse(profile, :button) %></li> | ||
17 | + | ||
18 | + <%= render_environment_features(:profile_actions) %> | ||
19 | + <% end %> | ||
20 | +</ul> |
app/views/blocks/profile_info_actions/_enterprise.html.erb
0 → 100644
@@ -0,0 +1,12 @@ | @@ -0,0 +1,12 @@ | ||
1 | +<ul> | ||
2 | + <%if logged_in? %> | ||
3 | + <%if !user.favorite_enterprises.include?(profile) %> | ||
4 | + <li><%= link_to content_tag('span', _('Add as favorite')), { :profile => user.identifier, :controller => 'favorite_enterprises', :action => 'add', :id => profile.id }, :class => 'button with-text icon-add', :title => _('Add enterprise as favorite') %></li> | ||
5 | + <% end %> | ||
6 | + <% end %> | ||
7 | + <% if profile.enable_contact? %> | ||
8 | + <li> <%= link_to content_tag('span', _('Send an e-mail')), {:profile => profile.identifier, :controller => 'contact', :action => 'new'}, {:id => 'enterprise-contact-button', :class => 'button with-text icon-menu-mail'} %> </li> | ||
9 | + <% end %> | ||
10 | + | ||
11 | + <li><%= report_abuse(profile, :button) %></li> | ||
12 | +</ul> |
app/views/blocks/profile_info_actions/_organization.html.erb
0 → 100644
@@ -0,0 +1,16 @@ | @@ -0,0 +1,16 @@ | ||
1 | +<ul> | ||
2 | + <%if logged_in? && (user != profile) %> | ||
3 | + | ||
4 | + <% if !user.already_request_friendship?(profile) and !user.is_a_friend?(profile) %> | ||
5 | + <li> | ||
6 | + <%= button(:add, content_tag('span', _('Add friend')), profile.add_url, :class => 'add-friend', :title => _("Add friend"), :style => 'position: relative;') %> | ||
7 | + </li> | ||
8 | + <% end %> | ||
9 | + | ||
10 | + <% if user.is_a_friend?(profile) && profile.enable_contact? %> | ||
11 | + <li> <%= link_to content_tag('span', _('Send an e-mail')), {:profile => profile.identifier, :controller => 'contact', :action => 'new'}, :class => 'button with-text icon-menu-mail' %> </li> | ||
12 | + <% end %> | ||
13 | + | ||
14 | + <li><%= report_abuse(profile, :button) %></li> | ||
15 | + <% end %> | ||
16 | +</ul> |
app/views/blocks/profile_info_actions/community.html.erb
@@ -1,20 +0,0 @@ | @@ -1,20 +0,0 @@ | ||
1 | -<ul> | ||
2 | - <li> | ||
3 | - <%= render "blocks/profile_info_actions/join_leave_community" %> | ||
4 | - </li> | ||
5 | - <% if logged_in? %> | ||
6 | - <% if profile.enable_contact? %> | ||
7 | - <li> | ||
8 | - <%= link_to content_tag('span', _('Send an e-mail')), | ||
9 | - { :profile => profile.identifier, | ||
10 | - :controller => 'contact', | ||
11 | - :action => 'new' }, | ||
12 | - {:class => 'button with-text icon-menu-mail', :title => _('Send an e-mail to the administrators')} %> | ||
13 | - </li> | ||
14 | - <% end %> | ||
15 | - | ||
16 | - <li><%= report_abuse(profile, :button) %></li> | ||
17 | - | ||
18 | - <%= render_environment_features(:profile_actions) %> | ||
19 | - <% end %> | ||
20 | -</ul> |
app/views/blocks/profile_info_actions/enterprise.html.erb
@@ -1,12 +0,0 @@ | @@ -1,12 +0,0 @@ | ||
1 | -<ul> | ||
2 | - <%if logged_in? %> | ||
3 | - <%if !user.favorite_enterprises.include?(profile) %> | ||
4 | - <li><%= link_to content_tag('span', _('Add as favorite')), { :profile => user.identifier, :controller => 'favorite_enterprises', :action => 'add', :id => profile.id }, :class => 'button with-text icon-add', :title => _('Add enterprise as favorite') %></li> | ||
5 | - <% end %> | ||
6 | - <% end %> | ||
7 | - <% if profile.enable_contact? %> | ||
8 | - <li> <%= link_to content_tag('span', _('Send an e-mail')), {:profile => profile.identifier, :controller => 'contact', :action => 'new'}, {:id => 'enterprise-contact-button', :class => 'button with-text icon-menu-mail'} %> </li> | ||
9 | - <% end %> | ||
10 | - | ||
11 | - <li><%= report_abuse(profile, :button) %></li> | ||
12 | -</ul> |