Commit 4f321345fb89ebdeb44e4bb879b426800bbdbc79
Exists in
master
and in
29 other branches
Merge branches 'master' and 'AI3268_template_management' into AI3268_template_management
Showing
1210 changed files
with
89174 additions
and
157212 deletions
Show diff stats
Too many changes.
To preserve performance only 100 of 1210 files displayed.
.ackrc
AUTHORS
... | ... | @@ -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 | 6 | Developers |
4 | 7 | ========== |
5 | 8 | |
9 | +Ábner Silva de Oliveira <abner.oliveira@serpro.gov.br> | |
6 | 10 | Alan Freihof Tygel <alantygel@gmail.com> |
11 | +alcampelo <alcampelo@alcampelo.(none)> | |
7 | 12 | Alessandro Palmeira <alessandro.palmeira@gmail.com> |
8 | 13 | Alessandro Palmeira + Caio C. Salgado <alessandro.palmeira@gmail.com> |
9 | 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 | 40 | Alessandro Palmeira + Paulo Meirelles <alessandro.palmeira@gmail.com> |
36 | 41 | Alessandro Palmeira + Paulo Meirelles + João M. M. da Silva <alessandro.palmeira@gmail.com> |
37 | 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 | 46 | Antonio Terceiro + Carlos Morais <terceiro@colivre.coop.br> |
39 | 47 | Antonio Terceiro + Paulo Meirelles <terceiro@colivre.coop.br> |
40 | 48 | Antonio Terceiro <terceiro@colivre.coop.br> |
49 | +Arthur Del Esposte <arthurmde@gmail.com> | |
50 | +Arthur Del Esposte <arthurmde@yahoo.com.br> | |
41 | 51 | Aurelio A. Heckert <aurelio@colivre.coop.br> |
42 | 52 | Braulio Bhavamitra <brauliobo@gmail.com> |
43 | 53 | Bráulio Bhavamitra <brauliobo@gmail.com> |
... | ... | @@ -65,6 +75,8 @@ Caio Salgado + Renan Teruo <caio.salgado@gmail.com> |
65 | 75 | Caio Salgado + Renan Teruo + Jefferson Fernandes <jeffs.fernandes@gmail.com> |
66 | 76 | Caio Salgado + Renan Teruo <renanteruoc@gmail.com> |
67 | 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 | 80 | Carlos Morais <carlos88morais@gmail.com> |
69 | 81 | Carlos Morais + Diego Araújo <diegoamc90@gmail.com> |
70 | 82 | Carlos Morais + Eduardo Morais <carlos88morais@gmail.com> |
... | ... | @@ -78,7 +90,9 @@ Daniel Alves + Diego Araújo + Guilherme Rojas <guilhermehrojas@gmail.com> |
78 | 90 | Daniel Alves + Guilherme Rojas <danpaulalves@gmail.com> |
79 | 91 | Daniel Alves + Rafael Manzo <rr.manzo@gmail.com> |
80 | 92 | Daniela Soares Feitosa <danielafeitosa@colivre.coop.br> |
93 | +Daniel Bucher <daniel.bucher88@gmail.com> | |
81 | 94 | Daniel Cunha <daniel@colivre.coop.br> |
95 | +David Carlos <ddavidcarlos1392@gmail.com> | |
82 | 96 | diegoamc <diegoamc90@gmail.com> |
83 | 97 | Diego Araújo + Alessandro Palmeira <diegoamc90@gmail.com> |
84 | 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 | 119 | Diego Araujo + Rodrigo Souto + Rafael Manzo <rr.manzo@gmail.com> |
106 | 120 | Diego + Jefferson <diegoamc90@gmail.com> |
107 | 121 | Diego Martinez <diegoamc90@gmail.com> |
108 | -Diego Martinez <diego@diego-K55A.(none)> | |
109 | 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 | 127 | Fernanda Lopes <nanda.listas+psl@gmail.com> |
111 | 128 | Francisco Marcelo A. Lima Júnior <francisco.lima-junior@serpro.gov.br> |
112 | 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 | 133 | Grazieno Pellegrino <grazieno@gmail.com> |
134 | +Gust <darksshades@hotmail.com> | |
135 | +Hebert Douglas <hebertdougl@gmail.com> | |
136 | +Hugo Melo <hugo@riseup.net> | |
114 | 137 | Isaac Canan <isaac@intelletto.com.br> |
115 | 138 | Italo Valcy <italo@dcc.ufba.br> |
116 | 139 | Jefferson Fernandes + Diego Araujo + Rafael Manzo <jeffs.fernandes@gmail.com> |
117 | 140 | Jefferson Fernandes + Joao M. M. da Silva <jeffs.fernandes@gmail.com> |
118 | 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 | 143 | João da Silva <jaodsilv@linux.ime.usp.br> |
120 | 144 | João Marco Maciel da Silva + Rafael Manzo + Renan Teruo <jaodsilv@linux.ime.usp.br> |
121 | 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 | 170 | João M. M. Silva + Renan Teruo <jaodsilv@linux.ime.usp.br> |
147 | 171 | Joenio Costa <joenio@colivre.coop.br> |
148 | 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 | 176 | Junior Silva <juniorsilva1001@gmail.com> |
150 | 177 | Junior Silva <juniorsilva7@juniorsilva-Aspire-5750Z.(none)> |
178 | +Junior Silva <juniorsilva@colivre.coop.br> | |
179 | +juniorsilva <juniorsilva@QonoS.localhost.localdomain> | |
151 | 180 | Keilla Menezes <keilla@colivre.coop.br> |
152 | 181 | Larissa Reis <larissa@colivre.coop.br> |
153 | 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 | 186 | Leandro Nunes dos Santos <leandronunes@gmail.com> |
155 | 187 | Leandro Nunes dos Santos <leandro.santos@serpro.gov.br> |
156 | 188 | LinguÁgil 2010 <linguagil.bahia@gmail.com> |
157 | 189 | Lucas Melo <lucas@colivre.coop.br> |
158 | 190 | Lucas Melo <lucaspradomelo@gmail.com> |
191 | +Luciano <lucianopcbr@gmail.com> | |
192 | +Luciano Prestes Cavalcanti <lucianopcbr@gmail.com> | |
159 | 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 | 196 | Martín Olivera <molivera@solar.org.ar> |
197 | +Michal Čihař <michal@cihar.com> | |
161 | 198 | Moises Machado <moises@colivre.coop.br> |
162 | 199 | Naíla Alves <naila@colivre.coop.br> |
163 | 200 | Nanda Lopes <nanda.listas+psl@gmail.com> |
201 | +Parley Martins <parleypachecomartins@gmail.com> | |
164 | 202 | Paulo Meirelles + Alessandro Palmeira + João M. M. da Silva <paulo@softwarelivre.org> |
165 | 203 | Paulo Meirelles + Alessandro Palmeira <paulo@softwarelivre.org> |
166 | 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 | 221 | Rafael Reggiani Manzo <rr.manzo@gmail.com> |
184 | 222 | Raphaël Rousseau <raph@r4f.org> |
185 | 223 | Raquel Lira <raquel.lira@gmail.com> |
224 | +Raquel <rcordioli@gmail.com> | |
186 | 225 | Renan Teruo + Caio Salgado <renanteruoc@gmail.com> |
187 | 226 | Renan Teruoc + Diego Araujo <renanteruoc@gmail.com> |
188 | 227 | Renan Teruo + Diego Araujo <renanteruoc@gmail.com> |
189 | 228 | Renan Teruo + Diego Araújo <renanteruoc@gmail.com> |
190 | 229 | Renan Teruo + Paulo Meirelles <renanteruoc@gmail.com> |
191 | 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 | 232 | Rodrigo Souto <rodrigo@colivre.coop.br> |
194 | 233 | Ronny Kursawe <kursawe.ronny@googlemail.com> |
195 | 234 | root <root@debian.sdr.serpro> |
196 | 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 | 241 | Valessio Brito <valessio@gmail.com> |
198 | 242 | vfcosta <vfcosta@gmail.com> |
243 | +Victor Carvalho <victorhugodf.ac@gmail.com> | |
199 | 244 | Victor Costa <vfcosta@gmail.com> |
245 | +Victor Hugo Alves de Carvalho <victorhugodf.ac@gmail.com> | |
200 | 246 | Vinicius Cubas Brand <viniciuscb@gmail.com> |
201 | 247 | Visita <visita@debian.(none)> |
202 | 248 | Yann Lugrin <yann.lugrin@liquid-concept.ch> | ... | ... |
... | ... | @@ -0,0 +1,124 @@ |
1 | +# Noosfero Development Policy | |
2 | + | |
3 | +## Developer Roles | |
4 | + | |
5 | +* *Developers* are everyone that is contributing code to Noosfero. | |
6 | +* *Committers* are the people with direct commit access to the Noosfero source | |
7 | + code. They are responsible for reviewing contributions from other developers | |
8 | + and integrating them in the Noosfero code base. They are the members of the | |
9 | + [Noosfero group on Gitlab](https://gitlab.com/groups/noosfero/members). | |
10 | +* *Release managers* are the people that are managing the release of a new | |
11 | + Noosfero version and/or the maintainance work of an existing Noosfero stable | |
12 | + branch. See MAINTAINANCE.md for details on the maintaince policy. | |
13 | + | |
14 | +## Development process | |
15 | + | |
16 | +* Every new feature or non-trivial bugfix should be reviewed by at least one | |
17 | + committer. This must be the case even if the original author is a committer. | |
18 | + | |
19 | + * In the case the original author is a committer, he/she should feel free to | |
20 | + commit directly if after 1 week nobody has provided any kind of feedback. | |
21 | + | |
22 | + * Developers who are not committers should feel free to ping committers if | |
23 | + they do not get feedback on their contributions after 1 week. | |
24 | + | |
25 | + * On GitLab, one can just add a comment to the merge request; one can also | |
26 | + @-mention specific committers or other developers who have expertise on | |
27 | + the area of the contribution. | |
28 | + | |
29 | + * Committers should follow the activity of the project, and try to help | |
30 | + reviewing contributions from others as much as possible. | |
31 | + | |
32 | + * On GitLab one can get emails for all activity on a project by setting the | |
33 | + [notification settings](https://gitlab.com/profile/notifications) to | |
34 | + "watch". | |
35 | + | |
36 | + * Anyone can help by reviewing contributions. Committers are the only ones | |
37 | + who can give the final approval to a contribution, but everyone is welcome | |
38 | + to help with code review, testing, etc. | |
39 | + | |
40 | + * See note above about setting up notification on GitLab. | |
41 | + | |
42 | +* Committers should feel free to push trivial (or urgent) changes directly. | |
43 | + There are no strict rule on what makes a change trivial or urgent; committers | |
44 | + are expected to exercise good judgement on a case by case basis. | |
45 | + | |
46 | + * Usually changes to the database are not trivial. | |
47 | + | |
48 | +* In the case of unsolvable conflict between commiters regarding any change to | |
49 | + the code, the current release manager(s) will have the final say in the | |
50 | + matter. | |
51 | + | |
52 | +* Release managers are responsible for stablishing a release schedule, and | |
53 | + about deciding when and what to release. | |
54 | + | |
55 | + * Release managers should announce release schedules to the project mailing | |
56 | + lists in advance. | |
57 | + | |
58 | + * The release schedule may include a period of feature freeze, during which | |
59 | + no new features or any other changes that are not pre-approved by the | |
60 | + release manager must be committed to the repository. | |
61 | + | |
62 | + * Committers must respect the release schedule and feature freezes. | |
63 | + | |
64 | +## Maintainance process | |
65 | + | |
66 | +### Not all feature releases will be maintained as a stable release | |
67 | + | |
68 | +We will be choosing specific release series to be maintained as stable | |
69 | +releases. | |
70 | + | |
71 | +This means that a given release is not guaranteed to be maintained as a stable | |
72 | +release, but does *not* mean it won't be. Any committer (or anyone, really) can | |
73 | +decide to maintain a given release as stable and seek help from others to do | |
74 | +so. | |
75 | + | |
76 | +### No merges from stable branches to master | |
77 | + | |
78 | +*All* changes must be submitted against the master branch first, and when | |
79 | +applicable, backported to the desired stable releases. Exceptions to this rules | |
80 | +are bug fixes that only apply to a given stable branch and not to master. | |
81 | + | |
82 | +In the past we had non-trivial changes accepted into stable releases while | |
83 | +master was way ahead (e.g. during the rails3 migration period), that made the | |
84 | +merge back into master very painful. By eliminating the need to do these | |
85 | +merges, we save time for the people responsible for the release, and eliminate | |
86 | +the possibility of human errors or oversights causing changes to be accepted | |
87 | +into stable that will be a problem to merge back into master. | |
88 | + | |
89 | +By getting all fixes in master first, we improve the chances that a future | |
90 | +release will not present regressions against bugs that should already be fixed, | |
91 | +but the fixes got lost in a big, complicated merge (and those won't exist | |
92 | +anymore, at least not from stable branches to master). | |
93 | + | |
94 | +After a fix gets into master, backporting changes into a stable release branch | |
95 | +is the responsibility of whoever is maintaing that branch, and those interested | |
96 | +in it. The stable branch release manager(s) are entitled the final say on any | |
97 | +matters related to that branch. | |
98 | + | |
99 | +## Apendix A: how to become a committer | |
100 | + | |
101 | +Every developer that wants to be a committer should create [an issue on | |
102 | +Gitlab](https://gitlab.com/noosfero/noosfero/issues) requesting to be added as | |
103 | +a committer. This request must include information about the requestor's | |
104 | +previous contributions to the project. | |
105 | + | |
106 | +If 2 or more commiters consider second the request, the requestor is accepted | |
107 | +as new commiter and added to the Noosfero group. | |
108 | + | |
109 | +The existing committers are free to choose whatever criteria they want to | |
110 | +second the request, but they must be sure that the new committer is a | |
111 | +responsible developer and knows what she/he is doing. They must be aware that | |
112 | +seconding these requests means seconding the actions of the new committer: if | |
113 | +the new committer screw up, her/his seconds screwed up. | |
114 | + | |
115 | +## Apendix B: how to become a release manager | |
116 | + | |
117 | +A new release manager for the development version of Noosfero (i.e. the one | |
118 | +that includes new features, a.k.a. the master branch) is apointed by the | |
119 | +current release manager, and must be a committer first. | |
120 | + | |
121 | +Release managers for stable branches are self-appointed, i.e. whoever takes the | |
122 | +work takes the role. In case of a conflict (e.g. 2+ different people want to do | |
123 | +the work but can't agree on working together), the development release manager | |
124 | +decides. | ... | ... |
Gemfile
1 | 1 | source "https://rubygems.org" |
2 | -gem 'rails' | |
3 | -gem 'fast_gettext' | |
4 | -gem 'acts-as-taggable-on' | |
5 | -gem 'prototype-rails' | |
6 | -gem 'prototype_legacy_helper', '0.0.0', :path => 'vendor/prototype_legacy_helper' | |
7 | -gem 'rails_autolink' | |
8 | -gem 'pg' | |
9 | -gem 'rmagick' | |
10 | -gem 'RedCloth' | |
11 | -gem 'will_paginate' | |
12 | -gem 'ruby-feedparser' | |
13 | -gem 'daemons' | |
14 | -gem 'thin' | |
15 | -gem 'hpricot' | |
16 | -gem 'nokogiri' | |
2 | +gem 'rails', '~> 3.2.19' | |
3 | +gem 'fast_gettext', '~> 0.6.8' | |
4 | +gem 'acts-as-taggable-on', '~> 3.0.2' | |
5 | +gem 'prototype-rails', '~> 3.2.1' | |
6 | +gem 'prototype_legacy_helper', '0.0.0', :path => 'vendor/prototype_legacy_helper' | |
7 | +gem 'rails_autolink', '~> 1.1.5' | |
8 | +gem 'pg', '~> 0.13.2' | |
9 | +gem 'rmagick', '~> 2.13.1' | |
10 | +gem 'RedCloth', '~> 4.2.9' | |
11 | +gem 'will_paginate', '~> 3.0.3' | |
12 | +gem 'ruby-feedparser', '~> 0.7' | |
13 | +gem 'daemons', '~> 1.1.5' | |
14 | +gem 'thin', '~> 1.3.1' | |
15 | +gem 'hpricot', '~> 0.8.6' | |
16 | +gem 'nokogiri', '~> 1.5.5' | |
17 | 17 | gem 'rake', :require => false |
18 | -gem 'rest-client' | |
19 | -gem 'exception_notification' | |
18 | +gem 'rest-client', '~> 1.6.7' | |
19 | +gem 'exception_notification', '~> 4.0.1' | |
20 | +gem 'gettext', '~> 2.2.1', :require => false, :group => :development | |
21 | +gem 'locale', '~> 2.0.5' | |
20 | 22 | |
21 | 23 | # FIXME list here all actual dependencies (i.e. the ones in debian/control), |
22 | 24 | # with their GEM names (not the Debian package names) |
23 | 25 | |
24 | 26 | group :production do |
25 | - gem 'dalli' | |
27 | + gem 'dalli', '~> 2.7.0' | |
26 | 28 | end |
27 | 29 | |
28 | 30 | group :test do |
29 | - gem 'rspec' | |
30 | - gem 'rspec-rails' | |
31 | - gem 'mocha', :require => false | |
31 | + gem 'rspec', '~> 2.10.0' | |
32 | + gem 'rspec-rails', '~> 2.10.1' | |
33 | + gem 'mocha', '~> 1.1.0', :require => false | |
32 | 34 | end |
33 | 35 | |
34 | 36 | group :cucumber do |
35 | - gem 'rake' | |
36 | - gem 'cucumber-rails', :require => false | |
37 | - gem 'capybara' | |
38 | - gem 'cucumber' | |
39 | - gem 'database_cleaner' | |
40 | - 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' | |
41 | 42 | end |
42 | 43 | |
43 | -# include plugin gemfiles | |
44 | -Dir.glob(File.join('config', 'plugins', '*')).each do |plugin| | |
45 | - plugin_gemfile = File.join(plugin, 'Gemfile') | |
46 | - eval File.read(plugin_gemfile) if File.exists?(plugin_gemfile) | |
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) | |
47 | 49 | end | ... | ... |
Gemfile.lock
... | ... | @@ -1,191 +0,0 @@ |
1 | -PATH | |
2 | - remote: vendor/prototype_legacy_helper | |
3 | - specs: | |
4 | - prototype_legacy_helper (0.0.0) | |
5 | - | |
6 | -GEM | |
7 | - remote: https://rubygems.org/ | |
8 | - specs: | |
9 | - RedCloth (4.2.9) | |
10 | - actionmailer (3.2.6) | |
11 | - actionpack (= 3.2.6) | |
12 | - mail (~> 2.4.4) | |
13 | - actionpack (3.2.6) | |
14 | - activemodel (= 3.2.6) | |
15 | - activesupport (= 3.2.6) | |
16 | - builder (~> 3.0.0) | |
17 | - erubis (~> 2.7.0) | |
18 | - journey (~> 1.0.1) | |
19 | - rack (~> 1.4.0) | |
20 | - rack-cache (~> 1.2) | |
21 | - rack-test (~> 0.6.1) | |
22 | - sprockets (~> 2.1.3) | |
23 | - activemodel (3.2.6) | |
24 | - activesupport (= 3.2.6) | |
25 | - builder (~> 3.0.0) | |
26 | - activerecord (3.2.6) | |
27 | - activemodel (= 3.2.6) | |
28 | - activesupport (= 3.2.6) | |
29 | - arel (~> 3.0.2) | |
30 | - tzinfo (~> 0.3.29) | |
31 | - activeresource (3.2.6) | |
32 | - activemodel (= 3.2.6) | |
33 | - activesupport (= 3.2.6) | |
34 | - activesupport (3.2.6) | |
35 | - i18n (~> 0.6) | |
36 | - multi_json (~> 1.0) | |
37 | - acts-as-taggable-on (3.0.2) | |
38 | - rails (>= 3, < 5) | |
39 | - arel (3.0.2) | |
40 | - builder (3.0.0) | |
41 | - capybara (2.1.0) | |
42 | - mime-types (>= 1.16) | |
43 | - nokogiri (>= 1.3.3) | |
44 | - rack (>= 1.0.0) | |
45 | - rack-test (>= 0.5.4) | |
46 | - xpath (~> 2.0) | |
47 | - childprocess (0.3.3) | |
48 | - ffi (~> 1.0.6) | |
49 | - cucumber (1.0.6) | |
50 | - builder (>= 2.1.2) | |
51 | - diff-lcs (>= 1.1.2) | |
52 | - gherkin (~> 2.4.18) | |
53 | - json (>= 1.4.6) | |
54 | - term-ansicolor (>= 1.0.6) | |
55 | - cucumber-rails (1.0.6) | |
56 | - capybara (>= 1.1.1) | |
57 | - cucumber (>= 1.0.6) | |
58 | - nokogiri (>= 1.5.0) | |
59 | - daemons (1.1.5) | |
60 | - dalli (2.7.0) | |
61 | - database_cleaner (1.2.0) | |
62 | - diff-lcs (1.1.3) | |
63 | - erubis (2.7.0) | |
64 | - eventmachine (0.12.10) | |
65 | - exception_notification (4.0.1) | |
66 | - actionmailer (>= 3.0.4) | |
67 | - activesupport (>= 3.0.4) | |
68 | - fast_gettext (0.6.8) | |
69 | - ffi (1.0.11) | |
70 | - gherkin (2.4.21) | |
71 | - json (>= 1.4.6) | |
72 | - hike (1.2.1) | |
73 | - hpricot (0.8.6) | |
74 | - i18n (0.6.0) | |
75 | - journey (1.0.3) | |
76 | - json (1.7.3) | |
77 | - mail (2.4.4) | |
78 | - i18n (>= 0.4.0) | |
79 | - mime-types (~> 1.16) | |
80 | - treetop (~> 1.4.8) | |
81 | - metaclass (0.0.1) | |
82 | - mime-types (1.19) | |
83 | - mocha (0.11.3) | |
84 | - metaclass (~> 0.0.1) | |
85 | - multi_json (1.3.6) | |
86 | - nokogiri (1.5.5) | |
87 | - pg (0.13.2) | |
88 | - polyglot (0.3.3) | |
89 | - prototype-rails (3.2.1) | |
90 | - rails (~> 3.2) | |
91 | - rack (1.4.1) | |
92 | - rack-cache (1.2) | |
93 | - rack (>= 0.4) | |
94 | - rack-ssl (1.3.2) | |
95 | - rack | |
96 | - rack-test (0.6.1) | |
97 | - rack (>= 1.0) | |
98 | - rails (3.2.6) | |
99 | - actionmailer (= 3.2.6) | |
100 | - actionpack (= 3.2.6) | |
101 | - activerecord (= 3.2.6) | |
102 | - activeresource (= 3.2.6) | |
103 | - activesupport (= 3.2.6) | |
104 | - bundler (~> 1.0) | |
105 | - railties (= 3.2.6) | |
106 | - rails_autolink (1.1.5) | |
107 | - rails (> 3.1) | |
108 | - railties (3.2.6) | |
109 | - actionpack (= 3.2.6) | |
110 | - activesupport (= 3.2.6) | |
111 | - rack-ssl (~> 1.3.2) | |
112 | - rake (>= 0.8.7) | |
113 | - rdoc (~> 3.4) | |
114 | - thor (>= 0.14.6, < 2.0) | |
115 | - rake (0.9.2.2) | |
116 | - rdoc (3.9.4) | |
117 | - rest-client (1.6.7) | |
118 | - mime-types (>= 1.16) | |
119 | - rmagick (2.13.1) | |
120 | - rspec (2.10.0) | |
121 | - rspec-core (~> 2.10.0) | |
122 | - rspec-expectations (~> 2.10.0) | |
123 | - rspec-mocks (~> 2.10.0) | |
124 | - rspec-core (2.10.1) | |
125 | - rspec-expectations (2.10.0) | |
126 | - diff-lcs (~> 1.1.3) | |
127 | - rspec-mocks (2.10.1) | |
128 | - rspec-rails (2.10.1) | |
129 | - actionpack (>= 3.0) | |
130 | - activesupport (>= 3.0) | |
131 | - railties (>= 3.0) | |
132 | - rspec (~> 2.10.0) | |
133 | - ruby-feedparser (0.7) | |
134 | - rubyzip (1.1.2) | |
135 | - selenium-webdriver (2.39.0) | |
136 | - childprocess (>= 0.2.5) | |
137 | - multi_json (~> 1.0) | |
138 | - rubyzip (~> 1.0) | |
139 | - websocket (~> 1.0.4) | |
140 | - sprockets (2.1.3) | |
141 | - hike (~> 1.2) | |
142 | - multi_json (~> 1.0) | |
143 | - rack (~> 1.0) | |
144 | - tilt (~> 1.1, != 1.3.0) | |
145 | - term-ansicolor (1.0.7) | |
146 | - thin (1.3.1) | |
147 | - daemons (>= 1.0.9) | |
148 | - eventmachine (>= 0.12.6) | |
149 | - rack (>= 1.0.0) | |
150 | - thor (0.15.3) | |
151 | - tilt (1.3.3) | |
152 | - treetop (1.4.10) | |
153 | - polyglot | |
154 | - polyglot (>= 0.3.1) | |
155 | - tzinfo (0.3.33) | |
156 | - websocket (1.0.7) | |
157 | - will_paginate (3.0.3) | |
158 | - xpath (2.0.0) | |
159 | - nokogiri (~> 1.3) | |
160 | - | |
161 | -PLATFORMS | |
162 | - ruby | |
163 | - | |
164 | -DEPENDENCIES | |
165 | - RedCloth | |
166 | - acts-as-taggable-on | |
167 | - capybara | |
168 | - cucumber | |
169 | - cucumber-rails | |
170 | - daemons | |
171 | - dalli | |
172 | - database_cleaner | |
173 | - exception_notification | |
174 | - fast_gettext | |
175 | - hpricot | |
176 | - mocha | |
177 | - nokogiri | |
178 | - pg | |
179 | - prototype-rails | |
180 | - prototype_legacy_helper (= 0.0.0)! | |
181 | - rails | |
182 | - rails_autolink | |
183 | - rake | |
184 | - rest-client | |
185 | - rmagick | |
186 | - rspec | |
187 | - rspec-rails | |
188 | - ruby-feedparser | |
189 | - selenium-webdriver | |
190 | - thin | |
191 | - will_paginate |
INSTALL.md
... | ... | @@ -186,8 +186,8 @@ Apache instalation |
186 | 186 | |
187 | 187 | # apt-get install apache2 |
188 | 188 | |
189 | -Apache configuration | |
190 | --------------------- | |
189 | +Configuration - noosfero at / | |
190 | +----------------------------- | |
191 | 191 | |
192 | 192 | First you have to enable the following some apache modules: |
193 | 193 | |
... | ... | @@ -257,6 +257,62 @@ Now restart your apache server (as root): |
257 | 257 | |
258 | 258 | # invoke-rc.d apache2 restart |
259 | 259 | |
260 | +Configuration - noosfero at a /subdirectory | |
261 | +------------------------------------------- | |
262 | + | |
263 | +This section describes how to configure noosfero at a subdirectory, what is | |
264 | +specially useful when you want Noosfero to share a domain name with other | |
265 | +applications. For example you can host noosfero at yourdomain.com/social, a | |
266 | +webmail application at yourdomain.com/webmail, and have a static HTML website | |
267 | +at yourdomain.com/. | |
268 | + | |
269 | +**NOTE:** Some plugins might not work well with this setting. Before deploying | |
270 | +this setting, make sure you test that everything you need works properly with | |
271 | +it. | |
272 | + | |
273 | +The configuration is similar to the main configuration instructions, except for | |
274 | +the following points. In the description below, replace '/subdirectory' with | |
275 | +the actual subdirectory you want. | |
276 | + | |
277 | +1) add a `prefix: /subdirectory` line to your thin configuration file (thin.yml). | |
278 | + | |
279 | +1.1) remember to restart the noosfero application server whenever you make | |
280 | +changes to that configuration file. | |
281 | + | |
282 | + # service noosfero restart | |
283 | + | |
284 | +2) add a line saying `export RAILS_RELATIVE_URL_ROOT=/subdirectory` to | |
285 | +/etc/default/noosfero (you can create it with just this line if it does not | |
286 | +exist already). | |
287 | + | |
288 | +3) You should add the following apache configuration to an existing virtual | |
289 | +host (plus the `<Proxy balancer://noosfero>` section as displayed above): | |
290 | + | |
291 | +``` | |
292 | +Alias /subdirectory /path/to/noosfero/public | |
293 | +<Directory "/path/to/noosfero/public"> | |
294 | + Options FollowSymLinks | |
295 | + AllowOverride None | |
296 | + Order Allow,Deny | |
297 | + Allow from all | |
298 | + | |
299 | + Include /path/to/noosfero/etc/noosfero/apache/cache.conf | |
300 | + | |
301 | + RewriteEngine On | |
302 | + RewriteBase /subdirectory | |
303 | + # Rewrite index to check for static index.html | |
304 | + RewriteRule ^$ index.html [QSA] | |
305 | + # Rewrite to check for Rails cached page | |
306 | + RewriteRule ^([^.]+)$ $1.html [QSA] | |
307 | + RewriteCond %{REQUEST_FILENAME} !-f | |
308 | + RewriteRule ^(.*)$ http://localhost:3000%{REQUEST_URI} [P,QSA,L] | |
309 | +</Directory> | |
310 | +``` | |
311 | + | |
312 | +3.1) remember to reload the apache server whenever any apache configuration | |
313 | +file changes. | |
314 | + | |
315 | + # sudo service apache2 reload | |
260 | 316 | |
261 | 317 | Enabling exception notifications |
262 | 318 | ================================ | ... | ... |
Rakefile
1 | 1 | #!/usr/bin/env rake |
2 | + | |
2 | 3 | # Add your own tasks in files placed in lib/tasks ending in .rake, |
3 | 4 | # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. |
4 | 5 | |
5 | 6 | require File.expand_path('../config/application', __FILE__) |
6 | 7 | |
7 | 8 | Noosfero::Application.load_tasks |
9 | + | |
10 | +[ | |
11 | + "baseplugins/*/{tasks,lib/tasks,rails/tasks}/**/*.rake", | |
12 | + "config/plugins/*/{tasks,lib/tasks,rails/tasks}/**/*.rake", | |
13 | + "config/plugins/*/vendor/plugins/*/{tasks,lib/tasks,rails/tasks}/**/*.rake", | |
14 | +].map do |pattern| | |
15 | + Dir.glob(pattern).sort | |
16 | +end.flatten.each do |taskfile| | |
17 | + load taskfile | |
18 | +end | ... | ... |
Vagrantfile
... | ... | @@ -3,7 +3,7 @@ |
3 | 3 | |
4 | 4 | VAGRANTFILE_API_VERSION = "2" |
5 | 5 | Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| |
6 | - config.vm.box = "debian-wheezy" | |
6 | + config.vm.box = ENV.fetch('VAGRANT_BOX', "debian-wheezy") | |
7 | 7 | config.vm.network :forwarded_port, host: 3000, guest: 3000 |
8 | 8 | config.vm.provision :shell do |shell| |
9 | 9 | shell.inline = 'su vagrant -c /vagrant/script/vagrant' | ... | ... |
app/controllers/admin/admin_panel_controller.rb
... | ... | @@ -71,4 +71,22 @@ class AdminPanelController < AdminController |
71 | 71 | end |
72 | 72 | end |
73 | 73 | end |
74 | + | |
75 | + def manage_organizations_status | |
76 | + scope = environment.organizations | |
77 | + @filter = params[:filter] || 'any' | |
78 | + @title = "Organization profiles" | |
79 | + @title = @title+" - "+@filter if @filter != 'any' | |
80 | + | |
81 | + if @filter == 'enabled' | |
82 | + scope = scope.visible | |
83 | + elsif @filter == 'disabled' | |
84 | + scope = scope.disabled | |
85 | + end | |
86 | + | |
87 | + scope = scope.order('name ASC') | |
88 | + | |
89 | + @q = params[:q] | |
90 | + @collection = find_by_contents(:organizations, scope, @q, {:per_page => 10, :page => params[:npage]})[:results] | |
91 | + end | |
74 | 92 | end | ... | ... |
app/controllers/admin/categories_controller.rb
... | ... | @@ -45,9 +45,11 @@ class CategoriesController < AdminController |
45 | 45 | if request.post? |
46 | 46 | @category.update_attributes!(params[:category]) |
47 | 47 | @saved = true |
48 | + session[:notice] = _("Category %s saved." % @category.name) | |
48 | 49 | redirect_to :action => 'index' |
49 | 50 | end |
50 | 51 | rescue Exception => e |
52 | + session[:notice] = _('Could not save category.') | |
51 | 53 | render :action => 'edit' |
52 | 54 | end |
53 | 55 | end | ... | ... |
app/controllers/admin/environment_design_controller.rb
... | ... | @@ -3,9 +3,7 @@ class EnvironmentDesignController < BoxOrganizerController |
3 | 3 | protect 'edit_environment_design', :environment |
4 | 4 | |
5 | 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 | 7 | @available_blocks += plugins.dispatch(:extra_blocks, :type => Environment) |
10 | 8 | end |
11 | 9 | ... | ... |
app/controllers/admin/features_controller.rb
... | ... | @@ -51,4 +51,10 @@ class FeaturesController < AdminController |
51 | 51 | redirect_to :action => 'manage_fields' |
52 | 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 | 60 | end | ... | ... |
app/controllers/application_controller.rb
... | ... | @@ -7,6 +7,12 @@ class ApplicationController < ActionController::Base |
7 | 7 | before_filter :detect_stuff_by_domain |
8 | 8 | before_filter :init_noosfero_plugins |
9 | 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 | 17 | after_filter :set_csrf_cookie |
12 | 18 | |
... | ... | @@ -34,7 +40,7 @@ class ApplicationController < ActionController::Base |
34 | 40 | |
35 | 41 | theme_layout = theme_option(:layout) |
36 | 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 | 44 | else |
39 | 45 | 'application' |
40 | 46 | end |
... | ... | @@ -187,4 +193,8 @@ class ApplicationController < ActionController::Base |
187 | 193 | {:results => scope.paginate(paginate_options)} |
188 | 194 | end |
189 | 195 | |
196 | + def private_environment? | |
197 | + @environment.enabled?(:restrict_to_members) | |
198 | + end | |
199 | + | |
190 | 200 | end | ... | ... |
app/controllers/my_profile/cms_controller.rb
... | ... | @@ -4,6 +4,12 @@ class CmsController < MyProfileController |
4 | 4 | |
5 | 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 | 13 | def self.protect_if(*args) |
8 | 14 | before_filter(*args) do |c| |
9 | 15 | user, profile = c.send(:user), c.send(:profile) |
... | ... | @@ -143,6 +149,7 @@ class CmsController < MyProfileController |
143 | 149 | end |
144 | 150 | |
145 | 151 | @article.profile = profile |
152 | + @article.author = user | |
146 | 153 | @article.last_changed_by = user |
147 | 154 | @article.created_by = user |
148 | 155 | |
... | ... | @@ -195,7 +202,7 @@ class CmsController < MyProfileController |
195 | 202 | :profile => profile, |
196 | 203 | :parent => @parent, |
197 | 204 | :last_changed_by => user, |
198 | - :created_by => user, | |
205 | + :author => user, | |
199 | 206 | }, |
200 | 207 | :without_protection => true |
201 | 208 | ) |
... | ... | @@ -220,7 +227,7 @@ class CmsController < MyProfileController |
220 | 227 | @article = profile.articles.find(params[:id]) |
221 | 228 | if request.post? |
222 | 229 | @article.destroy |
223 | - session[:notice] = _("\"#{@article.name}\" was removed.") | |
230 | + session[:notice] = _("\"%s\" was removed." % @article.name) | |
224 | 231 | referer = Rails.application.routes.recognize_path URI.parse(request.referer).path rescue nil |
225 | 232 | if referer and referer[:controller] == 'cms' and referer[:action] != 'edit' |
226 | 233 | redirect_to referer | ... | ... |
app/controllers/my_profile/memberships_controller.rb
... | ... | @@ -21,6 +21,9 @@ class MembershipsController < MyProfileController |
21 | 21 | @back_to = params[:back_to] || url_for(:action => 'index') |
22 | 22 | if request.post? && @community.valid? |
23 | 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 | 27 | redirect_to @back_to |
25 | 28 | return |
26 | 29 | end | ... | ... |
app/controllers/my_profile/profile_editor_controller.rb
... | ... | @@ -16,14 +16,16 @@ class ProfileEditorController < MyProfileController |
16 | 16 | if request.post? |
17 | 17 | params[:profile_data][:fields_privacy] ||= {} if profile.person? && params[:profile_data].is_a?(Hash) |
18 | 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 | 27 | end |
25 | 28 | end |
26 | - end | |
27 | 29 | end |
28 | 30 | end |
29 | 31 | |
... | ... | @@ -72,10 +74,51 @@ class ProfileEditorController < MyProfileController |
72 | 74 | if request.post? |
73 | 75 | if @profile.destroy |
74 | 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 | 82 | else |
77 | 83 | session[:notice] = _('Could not delete profile') |
78 | 84 | end |
79 | 85 | end |
80 | 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 | 124 | end | ... | ... |
app/controllers/my_profile/tasks_controller.rb
... | ... | @@ -4,6 +4,7 @@ class TasksController < MyProfileController |
4 | 4 | |
5 | 5 | def index |
6 | 6 | @filter = params[:filter_type].blank? ? nil : params[:filter_type] |
7 | + @task_types = Task.pending_types_for(profile) | |
7 | 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 | 9 | @failed = params ? params[:failed] : {} |
9 | 10 | end | ... | ... |
app/controllers/public/account_controller.rb
... | ... | @@ -2,7 +2,7 @@ class AccountController < ApplicationController |
2 | 2 | |
3 | 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 | 6 | before_filter :redirect_if_logged_in, :only => [:login, :signup] |
7 | 7 | before_filter :protect_from_bots, :only => :signup |
8 | 8 | |
... | ... | @@ -15,11 +15,23 @@ class AccountController < ApplicationController |
15 | 15 | |
16 | 16 | def activate |
17 | 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 | 35 | else |
24 | 36 | session[:notice] = _("It looks like you're trying to activate an account. Perhaps have already activated this account?") |
25 | 37 | redirect_to :controller => :home |
... | ... | @@ -85,6 +97,7 @@ class AccountController < ApplicationController |
85 | 97 | @user.return_to = session[:return_to] |
86 | 98 | @person = Person.new(params[:profile_data]) |
87 | 99 | @person.environment = @user.environment |
100 | + | |
88 | 101 | if request.post? |
89 | 102 | if may_be_a_bot |
90 | 103 | set_signup_start_time_for_now |
... | ... | @@ -103,11 +116,20 @@ class AccountController < ApplicationController |
103 | 116 | invitation.update_attributes!({:friend => @user.person}) |
104 | 117 | invitation.finish |
105 | 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 | 127 | if @user.activated? |
107 | 128 | self.current_user = @user |
108 | 129 | check_join_in_community(@user) |
109 | 130 | go_to_signup_initial_page |
110 | 131 | else |
132 | + session[:notice] = _('Thanks for registering!') | |
111 | 133 | @register_pending = true |
112 | 134 | end |
113 | 135 | end |
... | ... | @@ -171,7 +193,7 @@ class AccountController < ApplicationController |
171 | 193 | else |
172 | 194 | @change_password.errors[:base] << _('Could not find any user with %s equal to "%s".') % [fields_label, params[:value]] |
173 | 195 | end |
174 | - rescue ActiveRecord::RecordInvald | |
196 | + rescue ActiveRecord::RecordInvalid | |
175 | 197 | @change_password.errors[:base] << _('Could not perform password recovery for the user.') |
176 | 198 | end |
177 | 199 | end | ... | ... |
app/controllers/public/catalog_controller.rb
... | ... | @@ -11,7 +11,7 @@ class CatalogController < PublicController |
11 | 11 | protected |
12 | 12 | |
13 | 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 | 15 | redirect_to :controller => 'profile', :profile => profile.identifier, :action => 'index' |
16 | 16 | end |
17 | 17 | end | ... | ... |
app/controllers/public/chat_controller.rb
... | ... | @@ -19,9 +19,13 @@ class ChatController < PublicController |
19 | 19 | def avatar |
20 | 20 | profile = environment.profiles.find_by_identifier(params[:id]) |
21 | 21 | filename, mimetype = profile_icon(profile, :minor, true) |
22 | - data = File.read(File.join(Rails.root, 'public', filename)) | |
23 | - render :text => data, :layout => false, :content_type => mimetype | |
24 | - expires_in 24.hours | |
22 | + if filename =~ /^(https?:)?\/\// | |
23 | + redirect_to filename | |
24 | + else | |
25 | + data = File.read(File.join(Rails.root, 'public', filename)) | |
26 | + render :text => data, :layout => false, :content_type => mimetype | |
27 | + expires_in 24.hours | |
28 | + end | |
25 | 29 | end |
26 | 30 | |
27 | 31 | def index | ... | ... |
app/controllers/public/content_viewer_controller.rb
... | ... | @@ -74,7 +74,7 @@ class ContentViewerController < ApplicationController |
74 | 74 | end |
75 | 75 | |
76 | 76 | def versions_diff |
77 | - path = params[:page].join('/') | |
77 | + path = params[:page] | |
78 | 78 | @page = profile.articles.find_by_path(path) |
79 | 79 | @v1, @v2 = @page.versions.find_by_version(params[:v1]), @page.versions.find_by_version(params[:v2]) |
80 | 80 | end |
... | ... | @@ -126,7 +126,7 @@ class ContentViewerController < ApplicationController |
126 | 126 | elsif !@page.display_to?(user) |
127 | 127 | if !profile.public? |
128 | 128 | private_profile_partial_parameters |
129 | - render :template => 'profile/_private_profile', :status => 403 | |
129 | + render :template => 'profile/_private_profile', :status => 403, :formats => [:html] | |
130 | 130 | allowed = false |
131 | 131 | else #if !profile.visible? |
132 | 132 | render_access_denied | ... | ... |
app/controllers/public/profile_controller.rb
... | ... | @@ -17,7 +17,11 @@ class ProfileController < PublicController |
17 | 17 | end |
18 | 18 | @tags = profile.article_tags |
19 | 19 | unless profile.display_info_to?(user) |
20 | - profile.visible? ? private_profile : invisible_profile | |
20 | + if profile.visible? | |
21 | + private_profile | |
22 | + else | |
23 | + invisible_profile | |
24 | + end | |
21 | 25 | end |
22 | 26 | end |
23 | 27 | |
... | ... | @@ -61,13 +65,13 @@ class ProfileController < PublicController |
61 | 65 | |
62 | 66 | def friends |
63 | 67 | if is_cache_expired?(profile.friends_cache_key(params)) |
64 | - @friends = profile.friends.includes(relations_to_include).paginate(:per_page => per_page, :page => params[:npage]) | |
68 | + @friends = profile.friends.includes(relations_to_include).paginate(:per_page => per_page, :page => params[:npage], :total_entries => profile.friends.count) | |
65 | 69 | end |
66 | 70 | end |
67 | 71 | |
68 | 72 | def members |
69 | 73 | if is_cache_expired?(profile.members_cache_key(params)) |
70 | - @members = profile.members_by_name.includes(relations_to_include).paginate(:per_page => members_per_page, :page => params[:npage]) | |
74 | + @members = profile.members_by_name.includes(relations_to_include).paginate(:per_page => members_per_page, :page => params[:npage], :total_entries => profile.members.count) | |
71 | 75 | end |
72 | 76 | end |
73 | 77 | |
... | ... | @@ -315,7 +319,7 @@ class ProfileController < PublicController |
315 | 319 | abuse_report = AbuseReport.new(params[:abuse_report]) |
316 | 320 | if !params[:content_type].blank? |
317 | 321 | article = params[:content_type].constantize.find(params[:content_id]) |
318 | - abuse_report.content = instance_eval(&article.reported_version) | |
322 | + abuse_report.content = article_reported_version(article) | |
319 | 323 | end |
320 | 324 | |
321 | 325 | user.register_report(abuse_report, profile) |
... | ... | @@ -394,6 +398,7 @@ class ProfileController < PublicController |
394 | 398 | |
395 | 399 | def private_profile |
396 | 400 | private_profile_partial_parameters |
401 | + render :action => 'index', :status => 403 | |
397 | 402 | end |
398 | 403 | |
399 | 404 | def invisible_profile | ... | ... |
app/controllers/public/search_controller.rb
... | ... | @@ -90,10 +90,14 @@ class SearchController < PublicController |
90 | 90 | end |
91 | 91 | |
92 | 92 | def events |
93 | - year = (params[:year] ? params[:year].to_i : Date.today.year) | |
94 | - month = (params[:month] ? params[:month].to_i : Date.today.month) | |
95 | - day = (params[:day] ? params[:day].to_i : Date.today.day) | |
96 | - @date = build_date(year, month, day) | |
93 | + if params[:year].blank? && params[:year].blank? && params[:day].blank? | |
94 | + @date = Date.today | |
95 | + else | |
96 | + year = (params[:year] ? params[:year].to_i : Date.today.year) | |
97 | + month = (params[:month] ? params[:month].to_i : Date.today.month) | |
98 | + day = (params[:day] ? params[:day].to_i : 1) | |
99 | + @date = build_date(year, month, day) | |
100 | + end | |
97 | 101 | date_range = (@date - 1.month).at_beginning_of_month..(@date + 1.month).at_end_of_month |
98 | 102 | |
99 | 103 | @events = [] | ... | ... |
app/helpers/application_helper.rb
... | ... | @@ -304,7 +304,7 @@ module ApplicationHelper |
304 | 304 | def partial_for_class(klass, prefix=nil, suffix=nil) |
305 | 305 | raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' if klass.nil? |
306 | 306 | name = klass.name.underscore |
307 | - controller.view_paths.reverse_each do |view_path| | |
307 | + controller.view_paths.each do |view_path| | |
308 | 308 | partial = partial_for_class_in_view_path(klass, view_path, prefix, suffix) |
309 | 309 | return partial if partial |
310 | 310 | end |
... | ... | @@ -312,13 +312,13 @@ module ApplicationHelper |
312 | 312 | raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' |
313 | 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 | 322 | end |
323 | 323 | |
324 | 324 | def user |
... | ... | @@ -433,19 +433,19 @@ module ApplicationHelper |
433 | 433 | end |
434 | 434 | |
435 | 435 | def theme_site_title |
436 | - theme_include('site_title') | |
436 | + @theme_site_title ||= theme_include 'site_title' | |
437 | 437 | end |
438 | 438 | |
439 | 439 | def theme_header |
440 | - theme_include('header') | |
440 | + @theme_header ||= theme_include 'header' | |
441 | 441 | end |
442 | 442 | |
443 | 443 | def theme_footer |
444 | - theme_include('footer') | |
444 | + @theme_footer ||= theme_include 'footer' | |
445 | 445 | end |
446 | 446 | |
447 | 447 | def theme_extra_navigation |
448 | - theme_include('navigation') | |
448 | + @theme_extra_navigation ||= theme_include 'navigation' | |
449 | 449 | end |
450 | 450 | |
451 | 451 | def is_testing_theme |
... | ... | @@ -482,7 +482,12 @@ module ApplicationHelper |
482 | 482 | '/images/icons-app/enterprise-'+ size.to_s() +'.png' |
483 | 483 | end |
484 | 484 | else |
485 | - '/images/icons-app/person-'+ size.to_s() +'.png' | |
485 | + pixels = Image.attachment_options[:thumbnails][size].split('x').first | |
486 | + gravatar_profile_image_url( | |
487 | + profile.email, | |
488 | + :size => pixels, | |
489 | + :d => gravatar_default | |
490 | + ) | |
486 | 491 | end |
487 | 492 | filename = default_or_themed_icon(icon) |
488 | 493 | end |
... | ... | @@ -602,7 +607,7 @@ module ApplicationHelper |
602 | 607 | end |
603 | 608 | |
604 | 609 | def gravatar_default |
605 | - (respond_to?(:theme_option) && theme_option.present? && theme_option['gravatar']) || NOOSFERO_CONF['gravatar'] | |
610 | + (respond_to?(:theme_option) && theme_option.present? && theme_option['gravatar']) || NOOSFERO_CONF['gravatar'] || 'mm' | |
606 | 611 | end |
607 | 612 | |
608 | 613 | attr_reader :environment |
... | ... | @@ -669,13 +674,14 @@ module ApplicationHelper |
669 | 674 | html.join "\n" |
670 | 675 | end |
671 | 676 | |
677 | + def theme_javascript_src | |
678 | + script = File.join theme_path, 'theme.js' | |
679 | + script if File.exists? File.join(Rails.root, 'public', script) | |
680 | + end | |
681 | + | |
672 | 682 | def theme_javascript_ng |
673 | - script = File.join(theme_path, 'theme.js') | |
674 | - if File.exists?(File.join(Rails.root, 'public', script)) | |
675 | - javascript_include_tag script | |
676 | - else | |
677 | - nil | |
678 | - end | |
683 | + script = theme_javascript_src | |
684 | + javascript_include_tag script if script | |
679 | 685 | end |
680 | 686 | |
681 | 687 | def file_field_or_thumbnail(label, image, i) |
... | ... | @@ -902,13 +908,15 @@ module ApplicationHelper |
902 | 908 | end |
903 | 909 | |
904 | 910 | 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}" : '') | |
911 | + CGI.escapeHTML( | |
912 | + (@page ? @page.title + ' - ' : '') + | |
913 | + (@topic ? @topic.title + ' - ' : '') + | |
914 | + (@section ? @section.title + ' - ' : '') + | |
915 | + (@toc ? _('Online Manual') + ' - ' : '') + | |
916 | + (controller.controller_name == 'chat' ? _('Chat') + ' - ' : '') + | |
917 | + (profile ? profile.short_name : environment.name) + | |
918 | + (@category ? " - #{@category.full_name}" : '') | |
919 | + ) | |
912 | 920 | end |
913 | 921 | |
914 | 922 | # DEPRECATED. Do not use this. |
... | ... | @@ -1095,7 +1103,7 @@ module ApplicationHelper |
1095 | 1103 | result |
1096 | 1104 | end |
1097 | 1105 | |
1098 | - def manage_link(list, kind) | |
1106 | + def manage_link(list, kind, title) | |
1099 | 1107 | if list.present? |
1100 | 1108 | link_to_all = nil |
1101 | 1109 | if list.count > 5 |
... | ... | @@ -1108,19 +1116,19 @@ module ApplicationHelper |
1108 | 1116 | if link_to_all |
1109 | 1117 | link << link_to_all |
1110 | 1118 | end |
1111 | - render :partial => "shared/manage_link", :locals => {:link => link, :kind => kind.to_s} | |
1119 | + render :partial => "shared/manage_link", :locals => {:link => link, :kind => kind.to_s, :title => title} | |
1112 | 1120 | end |
1113 | 1121 | end |
1114 | 1122 | |
1115 | 1123 | def manage_enterprises |
1116 | 1124 | return '' unless user && user.environment.enabled?(:display_my_enterprises_on_user_menu) |
1117 | - manage_link(user.enterprises, :enterprises).to_s | |
1125 | + manage_link(user.enterprises, :enterprises, _('My enterprises')).to_s | |
1118 | 1126 | end |
1119 | 1127 | |
1120 | 1128 | def manage_communities |
1121 | 1129 | return '' unless user && user.environment.enabled?(:display_my_communities_on_user_menu) |
1122 | 1130 | administered_communities = user.communities.more_popular.select {|c| c.admins.include? user} |
1123 | - manage_link(administered_communities, :communities).to_s | |
1131 | + manage_link(administered_communities, :communities, _('My communities')).to_s | |
1124 | 1132 | end |
1125 | 1133 | |
1126 | 1134 | def admin_link |
... | ... | @@ -1225,20 +1233,7 @@ module ApplicationHelper |
1225 | 1233 | def add_zoom_to_images |
1226 | 1234 | stylesheet_link_tag('jquery.fancybox') + |
1227 | 1235 | 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')) | |
1236 | + javascript_tag("apply_zoom_to_images(#{_('Zoom in').to_json})") | |
1242 | 1237 | end |
1243 | 1238 | |
1244 | 1239 | def render_dialog_error_messages(instance_name) |
... | ... | @@ -1293,11 +1288,13 @@ module ApplicationHelper |
1293 | 1288 | end |
1294 | 1289 | |
1295 | 1290 | 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 | |
1291 | + CGI.escapeHTML( | |
1292 | + if article.folder? | |
1293 | + _("Are you sure that you want to remove the folder \"%s\"? Note that all the items inside it will also be removed!") % article.name | |
1294 | + else | |
1295 | + _("Are you sure that you want to remove the item \"%s\"?") % article.name | |
1296 | + end | |
1297 | + ) | |
1301 | 1298 | end |
1302 | 1299 | |
1303 | 1300 | def expirable_link_to(expired, content, url, options = {}) |
... | ... | @@ -1371,7 +1368,7 @@ module ApplicationHelper |
1371 | 1368 | @message = _("The content here is available to %s's friends only.") % profile.short_name |
1372 | 1369 | else |
1373 | 1370 | @action = :join |
1374 | - @message = _('The contents in this community is available to members only.') | |
1371 | + @message = _('The contents in this profile is available to members only.') | |
1375 | 1372 | end |
1376 | 1373 | @no_design_blocks = true |
1377 | 1374 | end |
... | ... | @@ -1383,7 +1380,7 @@ module ApplicationHelper |
1383 | 1380 | # are old things that do not support it we are keeping this hot spot. |
1384 | 1381 | html = @plugins.pipeline(:parse_content, html, source).first |
1385 | 1382 | end |
1386 | - html | |
1383 | + html && html.html_safe | |
1387 | 1384 | end |
1388 | 1385 | |
1389 | 1386 | def convert_macro(html, source) |
... | ... | @@ -1413,4 +1410,14 @@ module ApplicationHelper |
1413 | 1410 | content_tag('ul', article.versions.map {|v| link_to("r#{v.version}", @page.url.merge(:version => v.version))}) |
1414 | 1411 | end |
1415 | 1412 | |
1413 | + def labelled_colorpicker_field(human_name, object_name, method, options = {}) | |
1414 | + options[:id] ||= 'text-field-' + FormsHelper.next_id_number | |
1415 | + content_tag('label', human_name, :for => options[:id], :class => 'formlabel') + | |
1416 | + colorpicker_field(object_name, method, options.merge(:class => 'colorpicker_field')) | |
1417 | + end | |
1418 | + | |
1419 | + def colorpicker_field(object_name, method, options = {}) | |
1420 | + text_field(object_name, method, options.merge(:class => 'colorpicker_field')) | |
1421 | + end | |
1422 | + | |
1416 | 1423 | end | ... | ... |
app/helpers/article_helper.rb
... | ... | @@ -3,6 +3,12 @@ module ArticleHelper |
3 | 3 | include PrototypeHelper |
4 | 4 | include TokenHelper |
5 | 5 | |
6 | + def article_reported_version(article) | |
7 | + search_path = Rails.root.join('app', 'views', 'shared', 'reported_versions') | |
8 | + partial_path = File.join('shared', 'reported_versions', 'profile', partial_for_class_in_view_path(article.class, search_path)) | |
9 | + render_to_string(:partial => partial_path, :locals => {:article => article}) | |
10 | + end | |
11 | + | |
6 | 12 | def custom_options_for_article(article, tokenized_children) |
7 | 13 | @article = article |
8 | 14 | |
... | ... | @@ -83,6 +89,10 @@ module ArticleHelper |
83 | 89 | array.map { |object| {:id => object.id, :name => object.name} } |
84 | 90 | end |
85 | 91 | |
92 | + def prepare_to_token_input_by_label(array) | |
93 | + array.map { |object| {:label => object.name, :value => object.name} } | |
94 | + end | |
95 | + | |
86 | 96 | def cms_label_for_new_children |
87 | 97 | _('New article') |
88 | 98 | end | ... | ... |
app/helpers/block_helper.rb
... | ... | @@ -6,19 +6,20 @@ module BlockHelper |
6 | 6 | content_tag 'h3', content_tag('span', h(title)), :class => tag_class |
7 | 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 | 12 | <td> |
13 | 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 | 14 | </td> |
15 | 15 | <td>#{text_field_tag 'block[images][][address]', image[:address], :class => 'highlight-address', :size => 20}</td> |
16 | 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 | 18 | <td colspan=\"3\"><label>#{ |
19 | 19 | content_tag('span', _('Title')) + |
20 | 20 | text_field_tag('block[images][][title]', image[:title], :class => 'highlight-title', :size => 45) |
21 | 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 | 23 | </tr> |
23 | 24 | " |
24 | 25 | end | ... | ... |
app/helpers/blog_helper.rb
... | ... | @@ -17,13 +17,13 @@ module BlogHelper |
17 | 17 | _('Configure blog') |
18 | 18 | end |
19 | 19 | |
20 | - def list_posts(articles, format = 'full') | |
20 | + def list_posts(articles, format = 'full', paginate = true) | |
21 | 21 | pagination = will_paginate(articles, { |
22 | 22 | :param_name => 'npage', |
23 | 23 | :previous_label => _('« Newer posts'), |
24 | 24 | :next_label => _('Older posts »'), |
25 | 25 | :params => {:action=>"view_page", :page=>articles.first.parent.path.split('/'), :controller=>"content_viewer"} |
26 | - }) if articles.present? | |
26 | + }) if articles.present? && paginate | |
27 | 27 | content = [] |
28 | 28 | artic_len = articles.length |
29 | 29 | articles.each_with_index{ |art,i| |
... | ... | @@ -45,9 +45,9 @@ module BlogHelper |
45 | 45 | |
46 | 46 | def display_post(article, format = 'full') |
47 | 47 | no_comments = (format == 'full') ? false : true |
48 | + title = article_title(article, :no_comments => no_comments) | |
48 | 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 | 51 | end |
52 | 52 | |
53 | 53 | def display_full_format(article) | ... | ... |
app/helpers/categories_helper.rb
1 | 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 | 3 | TYPES = [ |
24 | 4 | [ _('General Category'), Category.to_s ], |
25 | 5 | [ _('Product Category'), ProductCategory.to_s ], |
26 | 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 | 9 | def select_category_type(field) |
47 | 10 | value = params[field] |
48 | 11 | labelled_form_field(_('Type of category'), select_tag('type', options_for_select(TYPES, value))) |
49 | 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 | 19 | #FIXME make this test |
52 | 20 | def selected_category_link(cat) |
53 | 21 | js_remove = "jQuery('#selected-category-#{cat.id}').remove();" | ... | ... |
app/helpers/content_viewer_helper.rb
... | ... | @@ -10,7 +10,7 @@ module ContentViewerHelper |
10 | 10 | end |
11 | 11 | |
12 | 12 | def number_of_comments(article) |
13 | - display_number_of_comments(article.comments.without_spam.count) | |
13 | + display_number_of_comments(article.comments_count - article.spam_comments_count.to_i) | |
14 | 14 | end |
15 | 15 | |
16 | 16 | def article_title(article, args = {}) |
... | ... | @@ -26,7 +26,7 @@ module ContentViewerHelper |
26 | 26 | end |
27 | 27 | title << content_tag('span', |
28 | 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 | 30 | content_tag('span', comments, :class => 'comments'), |
31 | 31 | :class => 'created-at' |
32 | 32 | ) | ... | ... |
app/helpers/folder_helper.rb
... | ... | @@ -5,15 +5,17 @@ module FolderHelper |
5 | 5 | include ShortFilename |
6 | 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 | 13 | :order => "updated_at DESC", |
12 | 14 | :per_page => 10, |
13 | 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 | 19 | else |
18 | 20 | content_tag('em', _('(empty folder)')) |
19 | 21 | end |
... | ... | @@ -23,21 +25,33 @@ module FolderHelper |
23 | 25 | articles.select {|article| article.display_to?(user)} |
24 | 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 | 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 | 43 | end |
33 | 44 | result = content_tag( |
34 | 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 | 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 | 55 | else |
42 | 56 | result |
43 | 57 | end | ... | ... |
app/helpers/layout_helper.rb
... | ... | @@ -17,6 +17,8 @@ module LayoutHelper |
17 | 17 | unless plugins_javascripts.empty? |
18 | 18 | output += javascript_include_tag plugins_javascripts, :cache => "cache/plugins-#{Digest::MD5.hexdigest plugins_javascripts.to_s}" |
19 | 19 | end |
20 | + output += theme_javascript_ng.to_s | |
21 | + | |
20 | 22 | output |
21 | 23 | end |
22 | 24 | |
... | ... | @@ -27,6 +29,7 @@ module LayoutHelper |
27 | 29 | 'thickbox', |
28 | 30 | 'lightbox', |
29 | 31 | 'colorbox', |
32 | + 'inputosaurus', | |
30 | 33 | pngfix_stylesheet_path, |
31 | 34 | ] + tokeninput_stylesheets |
32 | 35 | plugins_stylesheets = @plugins.select(&:stylesheet?).map { |plugin| plugin.class.public_path('style.css') } |
... | ... | @@ -83,6 +86,10 @@ module LayoutHelper |
83 | 86 | theme_path + '/style.css' |
84 | 87 | end |
85 | 88 | |
89 | + def layout_template | |
90 | + if profile then profile.layout_template else environment.layout_template end | |
91 | + end | |
92 | + | |
86 | 93 | def addthis_javascript |
87 | 94 | if NOOSFERO_CONF['addthis_enabled'] |
88 | 95 | '<script src="https://s7.addthis.com/js/152/addthis_widget.js"></script>' |
... | ... | @@ -90,7 +97,7 @@ module LayoutHelper |
90 | 97 | end |
91 | 98 | |
92 | 99 | def meta_description_tag(article=nil) |
93 | - article ? truncate(strip_tags(article.body.to_s), :length => 200) : environment.name | |
100 | + article ? CGI.escapeHTML(truncate(strip_tags(article.body.to_s), :length => 200)) : environment.name | |
94 | 101 | end |
95 | 102 | end |
96 | 103 | ... | ... |
app/helpers/profile_helper.rb
1 | 1 | module ProfileHelper |
2 | 2 | |
3 | - def display_field(title, profile, field, force = false) | |
3 | + COMMON_CATEGORIES = ActiveSupport::OrderedHash.new | |
4 | + COMMON_CATEGORIES[:content] = [:blogs, :image_galleries, :events, :article_tags] | |
5 | + COMMON_CATEGORIES[:interests] = [:interests] | |
6 | + COMMON_CATEGORIES[:general] = nil | |
7 | + | |
8 | + PERSON_CATEGORIES = ActiveSupport::OrderedHash.new | |
9 | + PERSON_CATEGORIES[:basic_information] = [:nickname, :sex, :birth_date, :location, :privacy_setting, :created_at] | |
10 | + PERSON_CATEGORIES[:contact] = [:contact_phone, :cell_phone, :comercial_phone, :contact_information, :email, :personal_website, :jabber_id] | |
11 | + PERSON_CATEGORIES[:location] = [:address, :address_reference, :zip_code, :city, :state, :district, :country, :nationality] | |
12 | + PERSON_CATEGORIES[:work] = [:organization, :organization_website, :professional_activity] | |
13 | + PERSON_CATEGORIES[:study] = [:schooling, :formation, :area_of_study] | |
14 | + PERSON_CATEGORIES[:network] = [:friends, :communities, :enterprises] | |
15 | + PERSON_CATEGORIES.merge!(COMMON_CATEGORIES) | |
16 | + | |
17 | + ORGANIZATION_CATEGORIES = ActiveSupport::OrderedHash.new | |
18 | + ORGANIZATION_CATEGORIES[:basic_information] = [:display_name, :created_at, :foundation_year, :type, :language, :members_count, :location, :address_reference, :historic_and_current_context, :admins] | |
19 | + ORGANIZATION_CATEGORIES[:contact] = [:contact_person, :contact_phone, :contact_email, :organization_website, :jabber_id] | |
20 | + ORGANIZATION_CATEGORIES[:economic] = [:business_name, :acronym, :economic_activity, :legal_form, :products, :activities_short_description, :management_information] | |
21 | + ORGANIZATION_CATEGORIES.merge!(COMMON_CATEGORIES) | |
22 | + | |
23 | + CATEGORY_MAP = ActiveSupport::OrderedHash.new | |
24 | + CATEGORY_MAP[:person] = PERSON_CATEGORIES | |
25 | + CATEGORY_MAP[:organization] = ORGANIZATION_CATEGORIES | |
26 | + | |
27 | + FORCE = { | |
28 | + :person => [:privacy_setting], | |
29 | + :organization => [:privacy_setting, :location], | |
30 | + } | |
31 | + | |
32 | + MULTIPLE = { | |
33 | + :person => [:blogs, :image_galleries, :interests], | |
34 | + :organization => [:blogs, :image_galleries, :interests], | |
35 | + } | |
36 | + | |
37 | + CUSTOM_LABELS = { | |
38 | + :zip_code => _('ZIP code'), | |
39 | + :email => _('e-Mail'), | |
40 | + :jabber_id => _('Jabber'), | |
41 | + :birth_date => _('Date of birth'), | |
42 | + :created_at => _('Profile created at'), | |
43 | + :members_count => _('Members'), | |
44 | + :privacy_setting => _('Privacy setting'), | |
45 | + :article_tags => _('Tags') | |
46 | + } | |
47 | + | |
48 | + EXCEPTION = { | |
49 | + :person => [:image, :preferred_domain, :description, :tag_list], | |
50 | + :organization => [:image, :preferred_domain, :description, :tag_list, :address, :zip_code, :city, :state, :country, :district] | |
51 | + } | |
52 | + | |
53 | + def general_fields | |
54 | + categorized_fields = CATEGORY_MAP[kind].values.flatten | |
55 | + profile.class.fields.map(&:to_sym) - categorized_fields - EXCEPTION[kind] | |
56 | + end | |
57 | + | |
58 | + def kind | |
59 | + if profile.kind_of?(Person) | |
60 | + :person | |
61 | + else | |
62 | + :organization | |
63 | + end | |
64 | + end | |
65 | + | |
66 | + def title(field, entry = nil) | |
67 | + return self.send("#{field}_custom_title", entry) if MULTIPLE[kind].include?(field) && entry.present? | |
68 | + CUSTOM_LABELS[field.to_sym] || _(field.to_s.humanize) | |
69 | + end | |
70 | + | |
71 | + def display_field(field) | |
72 | + force = FORCE[kind].include?(field) | |
73 | + multiple = MULTIPLE[kind].include?(field) | |
4 | 74 | unless force || profile.may_display_field_to?(field, user) |
5 | 75 | return '' |
6 | 76 | end |
7 | - value = profile.send(field) | |
8 | - if !value.blank? | |
9 | - if block_given? | |
10 | - value = yield(value) | |
11 | - end | |
12 | - content_tag('tr', content_tag('td', title, :class => 'field-name') + content_tag('td', value)) | |
77 | + value = begin profile.send(field) rescue nil end | |
78 | + return '' if value.blank? | |
79 | + if value.kind_of?(Hash) | |
80 | + content = self.send("treat_#{field}", value) | |
81 | + content_tag('tr', content_tag('td', title(field), :class => 'field-name') + content_tag('td', content)) | |
13 | 82 | else |
14 | - '' | |
83 | + entries = multiple ? value : [] << value | |
84 | + entries.map do |entry| | |
85 | + content = self.send("treat_#{field}", entry) | |
86 | + unless content.blank? | |
87 | + content_tag('tr', content_tag('td', title(field, entry), :class => 'field-name') + content_tag('td', content)) | |
88 | + end | |
89 | + end.join("\n") | |
15 | 90 | end |
16 | 91 | end |
17 | 92 | |
18 | - def display_contact(profile) | |
19 | - fields = [] | |
20 | - fields << display_field(_('Address:'), profile, :address).html_safe | |
21 | - fields << display_field(_('ZIP code:'), profile, :zip_code).html_safe | |
22 | - fields << display_field(_('Contact phone:'), profile, :contact_phone).html_safe | |
23 | - fields << display_field(_('e-Mail:'), profile, :email) { |email| link_to_email(email) }.html_safe | |
24 | - fields << display_field(_('Personal website:'), profile, :personal_website).html_safe | |
25 | - fields << display_field(_('Jabber:'), profile, :jabber_id).html_safe | |
26 | - if fields.reject!(&:blank?).empty? | |
27 | - '' | |
28 | - else | |
29 | - content_tag('tr', content_tag('th', _('Contact'), { :colspan => 2 })) + fields.join.html_safe | |
93 | + def treat_email(email) | |
94 | + link_to_email(email) | |
95 | + end | |
96 | + | |
97 | + def treat_organization_website(url) | |
98 | + link_to(url, url) | |
99 | + end | |
100 | + | |
101 | + def treat_sex(gender) | |
102 | + { 'male' => _('Male'), 'female' => _('Female') }[gender] | |
103 | + end | |
104 | + | |
105 | + def treat_date(date) | |
106 | + show_date(date.to_date) | |
107 | + end | |
108 | + alias :treat_birth_date :treat_date | |
109 | + alias :treat_created_at :treat_date | |
110 | + | |
111 | + def treat_friends(friends) | |
112 | + link_to friends.count, :controller => 'profile', :action => 'friends' | |
113 | + end | |
114 | + | |
115 | + def treat_communities(communities) | |
116 | + link_to communities.count, :controller => "profile", :action => 'communities' | |
117 | + end | |
118 | + | |
119 | + def treat_enterprises(enterprises) | |
120 | + if environment.disabled?('disable_asset_enterprises') | |
121 | + link_to enterprises.count, :controller => "profile", :action => 'enterprises' | |
122 | + end | |
123 | + end | |
124 | + | |
125 | + def treat_members_count(count) | |
126 | + link_to count, :controller => 'profile', :action => 'members' | |
127 | + end | |
128 | + | |
129 | + def treat_products(products) | |
130 | + if profile.kind_of?(Enterprise) && profile.environment.enabled?('products_for_enterprises') | |
131 | + link_to _('Products/Services'), :controller => 'catalog', :action => 'index' | |
30 | 132 | end |
31 | 133 | end |
32 | 134 | |
33 | - def display_work_info(profile) | |
34 | - organization = display_field(_('Organization:'), profile, :organization) | |
35 | - organization_site = display_field(_('Organization website:'), profile, :organization_website) { |url| link_to(url, url) } | |
36 | - if organization.blank? && organization_site.blank? | |
37 | - '' | |
135 | + def treat_admins(admins) | |
136 | + profile.admins.map { |admin| link_to(admin.short_name, admin.url)}.join(', ') | |
137 | + end | |
138 | + | |
139 | + def treat_blogs(blog) | |
140 | + link_to(n_('One post', '%{num} posts', blog.posts.published.count) % { :num => blog.posts.published.count }, blog.url) | |
141 | + end | |
142 | + | |
143 | + def treat_image_galleries(gallery) | |
144 | + link_to(n_('One picture', '%{num} pictures', gallery.images.published.count) % { :num => gallery.images.published.count }, gallery.url) | |
145 | + end | |
146 | + | |
147 | + def treat_events(events) | |
148 | + link_to events.published.count, :controller => 'events', :action => 'events' | |
149 | + end | |
150 | + | |
151 | + def treat_article_tags(tags) | |
152 | + tag_cloud @tags, :id, { :action => 'tags' }, :max_size => 18, :min_size => 10 | |
153 | + end | |
154 | + | |
155 | + def treat_interests(interest) | |
156 | + link_to interest.name, :controller => 'search', :action => 'category_index', :category_path => interest.explode_path | |
157 | + end | |
158 | + | |
159 | + def article_custom_title(article) | |
160 | + article.name | |
161 | + end | |
162 | + alias :blogs_custom_title :article_custom_title | |
163 | + alias :image_galleries_custom_title :article_custom_title | |
164 | + | |
165 | + def interests_custom_title(interest) | |
166 | + '' | |
167 | + end | |
168 | + | |
169 | + def method_missing(method, *args, &block) | |
170 | + if method.to_s =~ /^treat_(.+)$/ | |
171 | + args[0] | |
172 | + elsif method.to_s =~ /^display_(.+)$/ && CATEGORY_MAP[kind].has_key?($1.to_sym) | |
173 | + category = $1.to_sym | |
174 | + fields = category == :general ? general_fields : CATEGORY_MAP[kind][category] | |
175 | + contents = [] | |
176 | + | |
177 | + fields.each do |field| | |
178 | + contents << display_field(field).html_safe | |
179 | + end | |
180 | + | |
181 | + contents = contents.delete_if(&:blank?) | |
182 | + | |
183 | + unless contents.empty? | |
184 | + content_tag('tr', content_tag('th', title(category), { :colspan => 2 })) + contents.join.html_safe | |
185 | + else | |
186 | + '' | |
187 | + end | |
38 | 188 | else |
39 | - content_tag('tr', content_tag('th', _('Work'), { :colspan => 2 })) + organization + organization_site | |
189 | + super | |
40 | 190 | end |
41 | 191 | end |
42 | 192 | ... | ... |
app/helpers/role_helper.rb
app/helpers/sweeper_helper.rb
... | ... | @@ -56,12 +56,12 @@ module SweeperHelper |
56 | 56 | if profile |
57 | 57 | profile.blocks.each {|block| |
58 | 58 | conditions = block.class.expire_on |
59 | - blocks_to_expire << block unless (conditions[:profile] & causes).empty? | |
59 | + blocks_to_expire << block unless (conditions[:profile] & causes).blank? | |
60 | 60 | } |
61 | 61 | end |
62 | 62 | environment.blocks.each {|block| |
63 | 63 | conditions = block.class.expire_on |
64 | - blocks_to_expire << block unless (conditions[:environment] & causes).empty? | |
64 | + blocks_to_expire << block unless (conditions[:environment] & causes).blank? | |
65 | 65 | } |
66 | 66 | |
67 | 67 | blocks_to_expire.uniq! | ... | ... |
... | ... | @@ -0,0 +1,51 @@ |
1 | +module TinymceHelper | |
2 | + include MacrosHelper | |
3 | + | |
4 | + def tinymce_js | |
5 | + output = '' | |
6 | + output += javascript_include_tag 'tinymce/js/tinymce/tinymce.min.js' | |
7 | + output += javascript_include_tag 'tinymce/js/tinymce/jquery.tinymce.min.js' | |
8 | + output += javascript_include_tag 'tinymce.js' | |
9 | + output += include_macro_js_files.to_s | |
10 | + output | |
11 | + end | |
12 | + | |
13 | + def tinymce_init_js options = {} | |
14 | + options.merge! :document_base_url => environment.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 | 18 | options[:on_add] ||= 'null' |
19 | 19 | options[:on_delete] ||= 'null' |
20 | 20 | options[:on_ready] ||= 'null' |
21 | + options[:query_param] ||= 'q' | |
21 | 22 | |
22 | 23 | result = text_field_tag(name, nil, text_field_options.merge(html_options.merge({:id => element_id}))) |
23 | 24 | result += javascript_tag("jQuery('##{element_id}') |
... | ... | @@ -30,7 +31,7 @@ module TokenHelper |
30 | 31 | searchDelay: #{options[:search_delay].to_json}, |
31 | 32 | preventDuplicates: #{options[:prevent_duplicates].to_json}, |
32 | 33 | backspaceDeleteItem: #{options[:backspace_delete_item].to_json}, |
33 | - queryParam: #{name.to_json}, | |
34 | + queryParam: #{options[:query_param].to_json}, | |
34 | 35 | tokenLimit: #{options[:token_limit].to_json}, |
35 | 36 | onResult: #{options[:on_result]}, |
36 | 37 | onAdd: #{options[:on_add]}, |
... | ... | @@ -48,4 +49,4 @@ module TokenHelper |
48 | 49 | result |
49 | 50 | end |
50 | 51 | |
51 | -end | |
52 | 52 | \ No newline at end of file |
53 | +end | ... | ... |
app/models/article.rb
... | ... | @@ -40,6 +40,12 @@ class Article < ActiveRecord::Base |
40 | 40 | # xss_terminate plugin can't sanitize array fields |
41 | 41 | before_save :sanitize_tag_list |
42 | 42 | |
43 | + before_create do |article| | |
44 | + if article.author | |
45 | + article.author_name = article.author.name | |
46 | + end | |
47 | + end | |
48 | + | |
43 | 49 | belongs_to :profile |
44 | 50 | validates_presence_of :profile_id, :name |
45 | 51 | validates_presence_of :slug, :path, :if => lambda { |article| !article.name.blank? } |
... | ... | @@ -48,6 +54,7 @@ class Article < ActiveRecord::Base |
48 | 54 | |
49 | 55 | 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 | 56 | |
57 | + belongs_to :author, :class_name => 'Person' | |
51 | 58 | belongs_to :last_changed_by, :class_name => 'Person', :foreign_key => 'last_changed_by_id' |
52 | 59 | belongs_to :created_by, :class_name => 'Person', :foreign_key => 'created_by_id' |
53 | 60 | |
... | ... | @@ -150,14 +157,17 @@ class Article < ActiveRecord::Base |
150 | 157 | self.profile |
151 | 158 | end |
152 | 159 | |
153 | - def self.human_attribute_name(attrib, options = {}) | |
160 | + def self.human_attribute_name_with_customization(attrib, options={}) | |
154 | 161 | case attrib.to_sym |
155 | 162 | when :name |
156 | 163 | _('Title') |
157 | 164 | else |
158 | - _(self.superclass.human_attribute_name(attrib)) | |
165 | + _(self.human_attribute_name_without_customization(attrib)) | |
159 | 166 | end |
160 | 167 | end |
168 | + class << self | |
169 | + alias_method_chain :human_attribute_name, :customization | |
170 | + end | |
161 | 171 | |
162 | 172 | def css_class_list |
163 | 173 | [self.class.name.to_css_class] |
... | ... | @@ -275,13 +285,6 @@ class Article < ActiveRecord::Base |
275 | 285 | end |
276 | 286 | end |
277 | 287 | |
278 | - def reported_version(options = {}) | |
279 | - article = self | |
280 | - search_path = Rails.root.join('app', 'views', 'shared', 'reported_versions') | |
281 | - partial_path = File.join('shared', 'reported_versions', partial_for_class_in_view_path(article.class, search_path)) | |
282 | - lambda { render_to_string(:partial => partial_path, :locals => {:article => article}) } | |
283 | - end | |
284 | - | |
285 | 288 | # returns the data of the article. Must be overriden in each subclass to |
286 | 289 | # provide the correct content for the article. |
287 | 290 | def data |
... | ... | @@ -456,10 +459,10 @@ class Article < ActiveRecord::Base |
456 | 459 | ['TextArticle', 'TextileArticle', 'TinyMceArticle'] |
457 | 460 | end |
458 | 461 | |
459 | - scope :published, :conditions => { :published => true } | |
460 | - scope :folders, lambda {|profile|{:conditions => { :type => profile.folder_types} }} | |
461 | - scope :no_folders, lambda {|profile|{:conditions => ['type NOT IN (?)', profile.folder_types]}} | |
462 | - scope :galleries, :conditions => { :type => 'Gallery' } | |
462 | + scope :published, :conditions => ['articles.published = ?', true] | |
463 | + scope :folders, lambda {|profile|{:conditions => ['articles.type IN (?)', profile.folder_types] }} | |
464 | + scope :no_folders, lambda {|profile|{:conditions => ['articles.type NOT IN (?)', profile.folder_types]}} | |
465 | + scope :galleries, :conditions => [ "articles.type IN ('Gallery')" ] | |
463 | 466 | scope :images, :conditions => { :is_image => true } |
464 | 467 | scope :text_articles, :conditions => [ 'articles.type IN (?)', text_article_types ] |
465 | 468 | scope :with_types, lambda { |types| { :conditions => [ 'articles.type IN (?)', types ] } } |
... | ... | @@ -469,7 +472,7 @@ class Article < ActiveRecord::Base |
469 | 472 | scope :more_recent, :order => "created_at DESC" |
470 | 473 | |
471 | 474 | def self.display_filter(user, profile) |
472 | - return {:conditions => ['published = ?', true]} if !user | |
475 | + return {:conditions => ['articles.published = ?', true]} if !user | |
473 | 476 | {:conditions => [" articles.published = ? OR |
474 | 477 | articles.last_changed_by_id = ? OR |
475 | 478 | articles.profile_id = ? OR |
... | ... | @@ -496,6 +499,7 @@ class Article < ActiveRecord::Base |
496 | 499 | end |
497 | 500 | |
498 | 501 | def allow_post_content?(user = nil) |
502 | + return true if allow_edit_topic?(user) | |
499 | 503 | user && (user.has_permission?('post_content', profile) || allow_publish_content?(user) && (user == author)) |
500 | 504 | end |
501 | 505 | |
... | ... | @@ -515,9 +519,14 @@ class Article < ActiveRecord::Base |
515 | 519 | end |
516 | 520 | |
517 | 521 | def allow_edit?(user) |
522 | + return true if allow_edit_topic?(user) | |
518 | 523 | allow_post_content?(user) || user && allow_members_to_edit && user.is_member_of?(profile) |
519 | 524 | end |
520 | 525 | |
526 | + def allow_edit_topic?(user) | |
527 | + self.belongs_to_forum? && (user == author) && user.present? && user.is_member_of?(profile) | |
528 | + end | |
529 | + | |
521 | 530 | def moderate_comments? |
522 | 531 | moderate_comments == true |
523 | 532 | end |
... | ... | @@ -632,35 +641,36 @@ class Article < ActiveRecord::Base |
632 | 641 | can_display_versions? && display_versions |
633 | 642 | end |
634 | 643 | |
635 | - def author(version_number = nil) | |
636 | - if version_number | |
637 | - version = self.versions.find_by_version(version_number) | |
638 | - author_id = version.last_changed_by_id if version | |
639 | - else | |
640 | - author_id = self.created_by_id | |
641 | - end | |
644 | + def get_version(version_number = nil) | |
645 | + version_number ? versions.find(:first, :order => 'version', :offset => version_number - 1) : versions.earliest | |
646 | + end | |
642 | 647 | |
643 | - environment.people.find_by_id(author_id) | |
648 | + def author_by_version(version_number = nil) | |
649 | + version_number ? profile.environment.people.find_by_id(get_version(version_number).author_id) : author | |
644 | 650 | end |
645 | 651 | |
646 | 652 | def author_name(version_number = nil) |
647 | - person = author(version_number) | |
648 | - person ? person.name : (setting[:author_name] || _('Unknown')) | |
653 | + person = author_by_version(version_number) | |
654 | + if version_number | |
655 | + person ? person.name : _('Unknown') | |
656 | + else | |
657 | + person ? person.name : (setting[:author_name] || _('Unknown')) | |
658 | + end | |
649 | 659 | end |
650 | 660 | |
651 | 661 | def author_url(version_number = nil) |
652 | - person = author(version_number) | |
662 | + person = author_by_version(version_number) | |
653 | 663 | person ? person.url : nil |
654 | 664 | end |
655 | 665 | |
656 | 666 | def author_id(version_number = nil) |
657 | - person = author(version_number) | |
667 | + person = author_by_version(version_number) | |
658 | 668 | person ? person.id : nil |
659 | 669 | end |
660 | 670 | |
661 | 671 | def version_license(version_number = nil) |
662 | 672 | return license if version_number.nil? |
663 | - profile.environment.licenses.find_by_id(versions.find_by_version(version_number).license_id) | |
673 | + profile.environment.licenses.find_by_id(get_version(version_number).license_id) | |
664 | 674 | end |
665 | 675 | |
666 | 676 | alias :active_record_cache_key :cache_key | ... | ... |
app/models/block.rb
... | ... | @@ -75,7 +75,7 @@ class Block < ActiveRecord::Base |
75 | 75 | if context[:article] |
76 | 76 | return context[:article] == owner.home_page |
77 | 77 | else |
78 | - return context[:request_path] == '/' | |
78 | + return home_page_path?(context[:request_path]) | |
79 | 79 | end |
80 | 80 | end |
81 | 81 | |
... | ... | @@ -83,7 +83,7 @@ class Block < ActiveRecord::Base |
83 | 83 | if context[:article] |
84 | 84 | return context[:article] != owner.home_page |
85 | 85 | else |
86 | - return context[:request_path] != '/' + (owner.kind_of?(Profile) ? owner.identifier : '') | |
86 | + return !home_page_path?(context[:request_path]) | |
87 | 87 | end |
88 | 88 | end |
89 | 89 | |
... | ... | @@ -114,7 +114,7 @@ class Block < ActiveRecord::Base |
114 | 114 | # blocks to choose one to include in the design. |
115 | 115 | # |
116 | 116 | # Must be redefined in subclasses to match the description of each block |
117 | - # type. | |
117 | + # type. | |
118 | 118 | def self.description |
119 | 119 | '(dummy)' |
120 | 120 | end |
... | ... | @@ -124,13 +124,13 @@ class Block < ActiveRecord::Base |
124 | 124 | # This method can return several types of objects: |
125 | 125 | # |
126 | 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. |
127 | - # * <tt>Hash</tt>: the hash is used to build an URL that is used as the address for a IFRAME. | |
127 | + # * <tt>Hash</tt>: the hash is used to build an URL that is used as the address for a IFRAME. | |
128 | 128 | # * <tt>Proc</tt>: the Proc is evaluated in the scope of BoxesHelper. The |
129 | 129 | # block can then use <tt>render</tt>, <tt>link_to</tt>, etc. |
130 | 130 | # |
131 | 131 | # The method can also return <tt>nil</tt>, which means "no content". |
132 | 132 | # |
133 | - # See BoxesHelper#extract_block_content for implementation details. | |
133 | + # See BoxesHelper#extract_block_content for implementation details. | |
134 | 134 | def content(args={}) |
135 | 135 | "This is block number %d" % self.id |
136 | 136 | end |
... | ... | @@ -192,7 +192,7 @@ class Block < ActiveRecord::Base |
192 | 192 | |
193 | 193 | # Override in your subclasses. |
194 | 194 | # Define which events and context should cause the block cache to expire |
195 | - # Possible events are: :article, :profile, :friendship, :category | |
195 | + # Possible events are: :article, :profile, :friendship, :category, :role_assignment | |
196 | 196 | # Possible contexts are: :profile, :environment |
197 | 197 | def self.expire_on |
198 | 198 | { |
... | ... | @@ -234,4 +234,26 @@ class Block < ActiveRecord::Base |
234 | 234 | duplicated_block |
235 | 235 | end |
236 | 236 | |
237 | + def copy_from(block) | |
238 | + self.settings = block.settings | |
239 | + self.position = block.position | |
240 | + end | |
241 | + | |
242 | + private | |
243 | + | |
244 | + def home_page_path | |
245 | + home_page_url = Noosfero.root('/') | |
246 | + | |
247 | + if owner.kind_of?(Profile) | |
248 | + home_page_url += "profile/" if owner.home_page.nil? | |
249 | + home_page_url += owner.identifier | |
250 | + end | |
251 | + | |
252 | + return home_page_url | |
253 | + end | |
254 | + | |
255 | + def home_page_path? path | |
256 | + return path == home_page_path || path == (home_page_path + '/') | |
257 | + end | |
258 | + | |
237 | 259 | end | ... | ... |
app/models/box.rb
... | ... | @@ -28,9 +28,6 @@ class Box < ActiveRecord::Base |
28 | 28 | CategoriesBlock, |
29 | 29 | CommunitiesBlock, |
30 | 30 | EnterprisesBlock, |
31 | - # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from | |
32 | - # the Noosfero core soon, see ActionItem3045 | |
33 | - EnvironmentStatisticsBlock, | |
34 | 31 | FansBlock, |
35 | 32 | FavoriteEnterprisesBlock, |
36 | 33 | FeedReaderBlock, |
... | ... | @@ -53,9 +50,6 @@ class Box < ActiveRecord::Base |
53 | 50 | CommunitiesBlock, |
54 | 51 | DisabledEnterpriseMessageBlock, |
55 | 52 | EnterprisesBlock, |
56 | - # TODO EnvironmentStatisticsBlock is DEPRECATED and will be removed from | |
57 | - # the Noosfero core soon, see ActionItem3045 | |
58 | - EnvironmentStatisticsBlock, | |
59 | 53 | FansBlock, |
60 | 54 | FavoriteEnterprisesBlock, |
61 | 55 | FeaturedProductsBlock, | ... | ... |
app/models/category.rb
... | ... | @@ -14,9 +14,6 @@ class Category < ActiveRecord::Base |
14 | 14 | validates_uniqueness_of :slug,:scope => [ :environment_id, :parent_id ], :message => N_('{fn} is already being used by another category.').fix_i18n |
15 | 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 | 17 | # Finds all top level categories for a given environment. |
21 | 18 | scope :top_level_for, lambda { |environment| |
22 | 19 | {:conditions => ['parent_id is null and environment_id = ?', environment.id ]} |
... | ... | @@ -42,6 +39,13 @@ class Category < ActiveRecord::Base |
42 | 39 | |
43 | 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 | 49 | scope :from_types, lambda { |types| |
46 | 50 | types.select{ |t| t.blank? }.empty? ? |
47 | 51 | { :conditions => { :type => types } } : |
... | ... | @@ -101,4 +105,12 @@ class Category < ActiveRecord::Base |
101 | 105 | self.children.find(:all, :conditions => {:display_in_menu => true}).empty? |
102 | 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 | 116 | end | ... | ... |
app/models/change_password.rb
... | ... | @@ -2,16 +2,19 @@ class ChangePassword < Task |
2 | 2 | |
3 | 3 | attr_accessor :password, :password_confirmation |
4 | 4 | |
5 | - def self.human_attribute_name(attrib, options = {}) | |
5 | + def self.human_attribute_name_with_customization(attrib, options={}) | |
6 | 6 | case attrib.to_sym |
7 | 7 | when :password |
8 | 8 | _('Password') |
9 | 9 | when :password_confirmation |
10 | 10 | _('Password Confirmation') |
11 | 11 | else |
12 | - _(self.superclass.human_attribute_name(attrib)) | |
12 | + _(self.human_attribute_name_without_customization(attrib)) | |
13 | 13 | end |
14 | 14 | end |
15 | + class << self | |
16 | + alias_method_chain :human_attribute_name, :customization | |
17 | + end | |
15 | 18 | |
16 | 19 | validates_presence_of :requestor |
17 | 20 | ... | ... |
app/models/comment.rb
... | ... | @@ -109,14 +109,17 @@ class Comment < ActiveRecord::Base |
109 | 109 | include Noosfero::Plugin::HotSpot |
110 | 110 | |
111 | 111 | include Spammable |
112 | + include CacheCounterHelper | |
112 | 113 | |
113 | 114 | def after_spam! |
114 | 115 | SpammerLogger.log(ip_address, self) |
115 | 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 | 118 | end |
117 | 119 | |
118 | 120 | def after_ham! |
119 | 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 | 123 | end |
121 | 124 | |
122 | 125 | def verify_and_notify | ... | ... |
app/models/community.rb
... | ... | @@ -50,16 +50,6 @@ class Community < Organization |
50 | 50 | super + FIELDS |
51 | 51 | end |
52 | 52 | |
53 | - validate :presence_of_required_fieds | |
54 | - | |
55 | - def presence_of_required_fieds | |
56 | - self.required_fields.each do |field| | |
57 | - if self.send(field).blank? | |
58 | - self.errors.add_on_blank(field) | |
59 | - end | |
60 | - end | |
61 | - end | |
62 | - | |
63 | 53 | def active_fields |
64 | 54 | environment ? environment.active_community_fields : [] |
65 | 55 | end | ... | ... |
app/models/domain.rb
app/models/enterprise.rb
... | ... | @@ -25,7 +25,10 @@ class Enterprise < Organization |
25 | 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 | 27 | settings_items :organization_website, :historic_and_current_context, :activities_short_description |
28 | + | |
28 | 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 | 33 | extend SetProfileRegionFromCityState::ClassMethods |
31 | 34 | set_profile_region_from_city_state |
... | ... | @@ -56,16 +59,6 @@ class Enterprise < Organization |
56 | 59 | super + FIELDS |
57 | 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 | 62 | def active_fields |
70 | 63 | environment ? environment.active_enterprise_fields : [] |
71 | 64 | end |
... | ... | @@ -104,7 +97,12 @@ class Enterprise < Organization |
104 | 97 | self.tasks.where(:type => 'EnterpriseActivation').first |
105 | 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 | 106 | return if enabled |
109 | 107 | # must be set first for the following to work |
110 | 108 | self.enabled = true | ... | ... |
app/models/environment.rb
... | ... | @@ -3,7 +3,7 @@ |
3 | 3 | # domains. |
4 | 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 | 8 | has_many :users |
9 | 9 | |
... | ... | @@ -124,6 +124,7 @@ class Environment < ActiveRecord::Base |
124 | 124 | 'organizations_are_moderated_by_default' => _("Organizations have moderated publication by default"), |
125 | 125 | 'enable_organization_url_change' => _("Allow organizations to change their URL"), |
126 | 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 | 128 | 'show_balloon_with_profile_links_when_clicked' => _('Show a balloon with profile links when a profile image is clicked'), |
128 | 129 | 'xmpp_chat' => _('XMPP/Jabber based chat'), |
129 | 130 | 'show_zoom_button_on_article_images' => _('Show a zoom link on all article images'), |
... | ... | @@ -132,7 +133,8 @@ class Environment < ActiveRecord::Base |
132 | 133 | 'send_welcome_email_to_new_users' => _('Send welcome e-mail to new users'), |
133 | 134 | 'allow_change_of_redirection_after_login' => _('Allow users to set the page to redirect after login'), |
134 | 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 | 139 | end |
138 | 140 | |
... | ... | @@ -175,9 +177,6 @@ class Environment < ActiveRecord::Base |
175 | 177 | |
176 | 178 | # "left" area |
177 | 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 | 180 | env.boxes[1].blocks << RecentDocumentsBlock.new |
182 | 181 | |
183 | 182 | # "right" area |
... | ... | @@ -303,6 +302,17 @@ class Environment < ActiveRecord::Base |
303 | 302 | settings[:signup_welcome_screen_body].present? |
304 | 303 | end |
305 | 304 | |
305 | + settings_items :members_whitelist_enabled, :type => :boolean, :default => false | |
306 | + settings_items :members_whitelist, :type => Array, :default => [] | |
307 | + | |
308 | + def in_whitelist?(person) | |
309 | + !members_whitelist_enabled || members_whitelist.include?(person.id) | |
310 | + end | |
311 | + | |
312 | + def members_whitelist=(members) | |
313 | + settings[:members_whitelist] = members.split(',').map(&:to_i) | |
314 | + end | |
315 | + | |
306 | 316 | def news_amount_by_folder=(amount) |
307 | 317 | settings[:news_amount_by_folder] = amount.to_i |
308 | 318 | end |
... | ... | @@ -650,6 +660,7 @@ class Environment < ActiveRecord::Base |
650 | 660 | url = 'http://' |
651 | 661 | url << (Noosfero.url_options.key?(:host) ? Noosfero.url_options[:host] : default_hostname) |
652 | 662 | url << ':' << Noosfero.url_options[:port].to_s if Noosfero.url_options.key?(:port) |
663 | + url << Noosfero.root('') | |
653 | 664 | url |
654 | 665 | end |
655 | 666 | |
... | ... | @@ -813,7 +824,7 @@ class Environment < ActiveRecord::Base |
813 | 824 | end |
814 | 825 | |
815 | 826 | def notification_emails |
816 | - [noreply_email.blank? ? nil : noreply_email].compact + admins.map(&:email) | |
827 | + [contact_email].select(&:present?) + admins.map(&:email) | |
817 | 828 | end |
818 | 829 | |
819 | 830 | after_create :create_templates | ... | ... |
app/models/environment_statistics_block.rb
... | ... | @@ -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/external_feed.rb
... | ... | @@ -13,6 +13,7 @@ class ExternalFeed < ActiveRecord::Base |
13 | 13 | attr_accessible :address, :enabled |
14 | 14 | |
15 | 15 | def add_item(title, link, date, content) |
16 | + return if content.blank? | |
16 | 17 | doc = Hpricot(content) |
17 | 18 | doc.search('*').each do |p| |
18 | 19 | if p.instance_of? Hpricot::Elem |
... | ... | @@ -30,6 +31,7 @@ class ExternalFeed < ActiveRecord::Base |
30 | 31 | article.source = link |
31 | 32 | article.profile = blog.profile |
32 | 33 | article.parent = blog |
34 | + article.author_name = self.feed_title | |
33 | 35 | unless blog.children.exists?(:slug => article.slug) |
34 | 36 | article.save! |
35 | 37 | article.delay.create_activity | ... | ... |
app/models/featured_products_block.rb
1 | 1 | class FeaturedProductsBlock < Block |
2 | 2 | |
3 | + attr_accessible :product_ids, :groups_of, :speed, :reflect | |
4 | + | |
3 | 5 | settings_items :product_ids, :type => Array, :default => [] |
4 | 6 | settings_items :groups_of, :type => :integer, :default => 3 |
5 | 7 | settings_items :speed, :type => :integer, :default => 1000 | ... | ... |
app/models/feed_reader_block.rb
app/models/highlights_block.rb
app/models/link_list_block.rb
... | ... | @@ -78,16 +78,17 @@ class LinkListBlock < Block |
78 | 78 | address |
79 | 79 | end |
80 | 80 | if add !~ /^[a-z]+:\/\// && add !~ /^\// |
81 | - 'http://' + add | |
81 | + '//' + add | |
82 | 82 | else |
83 | + if root = Noosfero.root | |
84 | + if !add.starts_with?(root) | |
85 | + add = root + add | |
86 | + end | |
87 | + end | |
83 | 88 | add |
84 | 89 | end |
85 | 90 | end |
86 | 91 | |
87 | - def editable? | |
88 | - true | |
89 | - end | |
90 | - | |
91 | 92 | def icons_options |
92 | 93 | ICONS.map do |i| |
93 | 94 | "<span title=\"#{i[1]}\" class=\"icon-#{i[0]}\" onclick=\"changeIcon(this, '#{i[0]}')\"></span>".html_safe |
... | ... | @@ -100,4 +101,5 @@ class LinkListBlock < Block |
100 | 101 | sanitizer = HTML::WhiteListSanitizer.new |
101 | 102 | sanitizer.sanitize(text) |
102 | 103 | end |
104 | + | |
103 | 105 | end | ... | ... |
app/models/location_block.rb
app/models/main_block.rb
... | ... | @@ -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 | 60 | \ No newline at end of file | ... | ... |
app/models/organization.rb
... | ... | @@ -30,6 +30,16 @@ class Organization < Profile |
30 | 30 | |
31 | 31 | scope :more_popular, :order => 'members_count DESC' |
32 | 32 | |
33 | + validate :presence_of_required_fieds, :unless => :is_template | |
34 | + | |
35 | + def presence_of_required_fieds | |
36 | + self.required_fields.each do |field| | |
37 | + if self.send(field).blank? | |
38 | + self.errors.add_on_blank(field) | |
39 | + end | |
40 | + end | |
41 | + end | |
42 | + | |
33 | 43 | def validation_methodology |
34 | 44 | self.validation_info ? self.validation_info.validation_methodology : nil |
35 | 45 | end |
... | ... | @@ -135,7 +145,11 @@ class Organization < Profile |
135 | 145 | end |
136 | 146 | |
137 | 147 | def notification_emails |
138 | - [contact_email.blank? ? nil : contact_email].compact + admins.map(&:email) | |
148 | + emails = [contact_email].select(&:present?) + admins.map(&:email) | |
149 | + if emails.empty? | |
150 | + emails << environment.contact_email | |
151 | + end | |
152 | + emails | |
139 | 153 | end |
140 | 154 | |
141 | 155 | def already_request_membership?(person) | ... | ... |
app/models/person.rb
... | ... | @@ -21,6 +21,12 @@ class Person < Profile |
21 | 21 | { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => [conditions] } |
22 | 22 | } |
23 | 23 | |
24 | + scope :by_role, lambda { |roles| | |
25 | + roles = [roles] unless roles.kind_of?(Array) | |
26 | + { :select => 'DISTINCT profiles.*', :joins => :role_assignments, :conditions => ['role_assignments.role_id IN (?)', | |
27 | +roles] } | |
28 | + } | |
29 | + | |
24 | 30 | def has_permission_with_plugins?(permission, profile) |
25 | 31 | permissions = [has_permission_without_plugins?(permission, profile)] |
26 | 32 | permissions += plugins.map do |plugin| |
... | ... | @@ -161,7 +167,7 @@ class Person < Profile |
161 | 167 | FIELDS |
162 | 168 | end |
163 | 169 | |
164 | - validate :presence_of_required_fields | |
170 | + validate :presence_of_required_fields, :unless => :is_template | |
165 | 171 | |
166 | 172 | def presence_of_required_fields |
167 | 173 | self.required_fields.each do |field| | ... | ... |
app/models/product_categories_block.rb
... | ... | @@ -33,7 +33,7 @@ class ProductCategoriesBlock < Block |
33 | 33 | end |
34 | 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 | 38 | def display |
39 | 39 | settings[:display].nil? ? 'catalog_only' : super | ... | ... |
app/models/products_block.rb
... | ... | @@ -49,17 +49,10 @@ class ProductsBlock < Block |
49 | 49 | |
50 | 50 | def products(reload = false) |
51 | 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 | 53 | else |
61 | - product_ids.map {|item| owner.products.find(item) } | |
62 | - end | |
54 | + owner.products.where(:id => product_ids) | |
55 | + end.compact | |
63 | 56 | end |
64 | 57 | |
65 | 58 | end | ... | ... |
app/models/profile.rb
... | ... | @@ -97,7 +97,7 @@ class Profile < ActiveRecord::Base |
97 | 97 | end |
98 | 98 | |
99 | 99 | def members_by_name |
100 | - members.order(:name) | |
100 | + members.order('profiles.name') | |
101 | 101 | end |
102 | 102 | |
103 | 103 | class << self |
... | ... | @@ -108,8 +108,8 @@ class Profile < ActiveRecord::Base |
108 | 108 | alias_method_chain :count, :distinct |
109 | 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 | 113 | end |
114 | 114 | |
115 | 115 | acts_as_having_boxes |
... | ... | @@ -121,6 +121,7 @@ class Profile < ActiveRecord::Base |
121 | 121 | end |
122 | 122 | |
123 | 123 | scope :visible, :conditions => { :visible => true } |
124 | + scope :disabled, :conditions => { :visible => false } | |
124 | 125 | scope :public, :conditions => { :visible => true, :public_profile => true } |
125 | 126 | |
126 | 127 | # Subclasses must override this method |
... | ... | @@ -346,16 +347,17 @@ class Profile < ActiveRecord::Base |
346 | 347 | end |
347 | 348 | |
348 | 349 | def copy_blocks_from(profile) |
350 | + template_boxes = profile.boxes.select{|box| box.position} | |
349 | 351 | self.boxes.destroy_all |
350 | - profile.boxes.each do |box| | |
351 | - new_box = Box.new | |
352 | + self.boxes = template_boxes.size.times.map { Box.new } | |
353 | + | |
354 | + template_boxes.each_with_index do |box, i| | |
355 | + new_box = self.boxes[i] | |
352 | 356 | new_box.position = box.position |
353 | - self.boxes << new_box | |
354 | 357 | box.blocks.each do |block| |
355 | 358 | 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 | |
359 | + new_block.copy_from(block) | |
360 | + new_box.blocks << new_block | |
359 | 361 | end |
360 | 362 | end |
361 | 363 | end |
... | ... | @@ -774,7 +776,7 @@ private :generate_url, :url_options |
774 | 776 | end |
775 | 777 | |
776 | 778 | include Noosfero::Plugin::HotSpot |
777 | - | |
779 | + | |
778 | 780 | def folder_types |
779 | 781 | types = Article.folder_types |
780 | 782 | plugins.dispatch(:content_types).each {|type| |
... | ... | @@ -898,6 +900,13 @@ private :generate_url, :url_options |
898 | 900 | end |
899 | 901 | |
900 | 902 | def disable |
903 | + self.visible = false | |
904 | + self.save | |
905 | + end | |
906 | + | |
907 | + def enable | |
908 | + self.visible = true | |
909 | + self.save | |
901 | 910 | end |
902 | 911 | |
903 | 912 | 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 | 73 | end |
74 | 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 | 76 | # this method finished the task. It calls #perform, which must be overriden |
81 | 77 | # by subclasses. At the end a message (as returned by #finish_message) is |
82 | 78 | # sent to the requestor with #notify_requestor. |
... | ... | @@ -254,6 +250,10 @@ class Task < ActiveRecord::Base |
254 | 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 | 257 | def opened? |
258 | 258 | status == Task::Status::ACTIVE || status == Task::Status::HIDDEN |
259 | 259 | end |
... | ... | @@ -285,8 +285,9 @@ class Task < ActiveRecord::Base |
285 | 285 | # If |
286 | 286 | def send_notification(action) |
287 | 287 | if sends_email? |
288 | - if self.requestor | |
289 | - TaskMailer.generic_message("task_#{action}", self) | |
288 | + if self.requestor && !self.requestor.notification_emails.empty? | |
289 | + message = TaskMailer.generic_message("task_#{action}", self) | |
290 | + message.deliver if message | |
290 | 291 | end |
291 | 292 | end |
292 | 293 | end | ... | ... |
app/models/user.rb
... | ... | @@ -5,7 +5,7 @@ require 'user_activation_job' |
5 | 5 | # Rails generator. |
6 | 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 | 10 | N_('Password') |
11 | 11 | N_('Password confirmation') |
... | ... | @@ -16,15 +16,18 @@ class User < ActiveRecord::Base |
16 | 16 | end |
17 | 17 | |
18 | 18 | # FIXME ugly workaround |
19 | - def self.human_attribute_name(attrib, options={}) | |
19 | + def self.human_attribute_name_with_customization(attrib, options={}) | |
20 | 20 | case attrib.to_sym |
21 | 21 | when :login |
22 | 22 | return [_('Username'), _('Email')].join(' / ') |
23 | 23 | when :email |
24 | 24 | return _('e-Mail') |
25 | - else _(self.superclass.human_attribute_name(attrib)) | |
25 | + else _(self.human_attribute_name_without_customization(attrib)) | |
26 | 26 | end |
27 | 27 | end |
28 | + class << self | |
29 | + alias_method_chain :human_attribute_name, :customization | |
30 | + end | |
28 | 31 | |
29 | 32 | before_create do |user| |
30 | 33 | if user.environment.nil? |
... | ... | @@ -47,8 +50,12 @@ class User < ActiveRecord::Base |
47 | 50 | |
48 | 51 | user.person = p |
49 | 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 | 59 | end |
53 | 60 | end |
54 | 61 | after_create :deliver_activation_code |
... | ... | @@ -137,6 +144,15 @@ class User < ActiveRecord::Base |
137 | 144 | end |
138 | 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 | 156 | def activated? |
141 | 157 | self.activation_code.nil? && !self.activated_at.nil? |
142 | 158 | end |
... | ... | @@ -185,6 +201,10 @@ class User < ActiveRecord::Base |
185 | 201 | Digest::MD5.hexdigest(password) |
186 | 202 | end |
187 | 203 | |
204 | + add_encryption_method :salted_md5 do |password, salt| | |
205 | + Digest::MD5.hexdigest(password+salt) | |
206 | + end | |
207 | + | |
188 | 208 | add_encryption_method :clear do |password, salt| |
189 | 209 | password |
190 | 210 | end |
... | ... | @@ -334,6 +354,7 @@ class User < ActiveRecord::Base |
334 | 354 | end |
335 | 355 | |
336 | 356 | def delay_activation_check |
357 | + return if person.is_template? | |
337 | 358 | Delayed::Job.enqueue(UserActivationJob.new(self.id), {:priority => 0, :run_at => 72.hours.from_now}) |
338 | 359 | end |
339 | 360 | end | ... | ... |
app/presenters/image.rb
... | ... | @@ -11,4 +11,9 @@ class FilePresenter::Image < FilePresenter |
11 | 11 | def short_description |
12 | 12 | _('Image (%s)') % content_type.split('/')[1].upcase |
13 | 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 | 19 | end | ... | ... |
app/sweepers/profile_sweeper.rb
... | ... | @@ -8,9 +8,6 @@ class ProfileSweeper # < ActiveRecord::Observer |
8 | 8 | end |
9 | 9 | |
10 | 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 | 11 | end |
15 | 12 | |
16 | 13 | protected |
... | ... | @@ -31,13 +28,6 @@ protected |
31 | 28 | expire_blogs(profile) if profile.organization? |
32 | 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 | 31 | def expire_blogs(profile) |
42 | 32 | profile.blogs.select{|b| !b.empty?}.each do |blog| |
43 | 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 | 13 | protected |
14 | 14 | |
15 | 15 | def expire_caches(role_assignment) |
16 | - expire_cache(role_assignment.accessor) | |
17 | - expire_cache(role_assignment.resource) if role_assignment.resource.respond_to?(:cache_keys) | |
16 | + expire_cache(role_assignment.accessor) if role_assignment.accessor.kind_of?(Profile) | |
17 | + expire_cache(role_assignment.resource) if role_assignment.resource.kind_of?(Profile) | |
18 | 18 | end |
19 | 19 | |
20 | 20 | def expire_cache(profile) |
21 | 21 | per_page = Noosfero::Constants::PROFILE_PER_PAGE |
22 | - profile.cache_keys(:per_page => per_page).each { |ck| | |
23 | - expire_timeout_fragment(ck) | |
24 | - } | |
22 | + | |
23 | + profile.cache_keys(:per_page => per_page).each { |ck| expire_timeout_fragment(ck) } | |
24 | + expire_timeout_fragment(profile.members_cache_key(:per_page => per_page)) | |
25 | 25 | |
26 | 26 | profile.blocks_to_expire_cache.each { |block| |
27 | 27 | blocks = profile.blocks.select{|b| b.kind_of?(block)} |
28 | 28 | BlockSweeper.expire_blocks(blocks) |
29 | 29 | } |
30 | + | |
31 | + expire_blocks_cache(profile, [:role_assignment]) | |
30 | 32 | end |
31 | 33 | |
32 | 34 | end | ... | ... |
app/views/account/_signup_form.html.erb
... | ... | @@ -136,8 +136,6 @@ |
136 | 136 | <script type="text/javascript"> |
137 | 137 | jQuery(function($) { |
138 | 138 | |
139 | - $('#signup-form #user_login').css('width', 335 - $('#signup-domain').outerWidth()); | |
140 | - | |
141 | 139 | $('#signup-form input[type=text], #signup-form textarea').each(function() { |
142 | 140 | $(this).bind('blur', function() { |
143 | 141 | if ($(this).val() == '') { | ... | ... |
app/views/account/signup.html.erb
... | ... | @@ -2,18 +2,36 @@ |
2 | 2 | <div id='thanks-for-signing'> |
3 | 3 | <% if environment.has_custom_welcome_screen? %> |
4 | 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 | 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 | 35 | <% end %> |
18 | 36 | </div> |
19 | 37 | <% else %> | ... | ... |
app/views/admin_panel/index.html.erb
... | ... | @@ -20,6 +20,7 @@ |
20 | 20 | <tr><td><%= link_to _('Users'), :controller => 'users' %></td></tr> |
21 | 21 | <tr><td><%= link_to _('Profile templates'), :controller => 'templates' %></td></tr> |
22 | 22 | <tr><td><%= link_to _('Fields'), :controller => 'features', :action => 'manage_fields' %></td></tr> |
23 | + <tr><td><%= link_to _('Manage organizations status'), :action => 'manage_organizations_status' %></td></tr> | |
23 | 24 | </table> |
24 | 25 | |
25 | 26 | ... | ... |
app/views/admin_panel/manage_organizations_status.html.erb
0 → 100644
... | ... | @@ -0,0 +1,69 @@ |
1 | +<h1><%= _('Manage organizations') %></h1> | |
2 | + | |
3 | +<%= form_tag( { :action => 'manage_organizations_status' }, :method => 'get', :class => 'users-search' ) do %> | |
4 | + | |
5 | + <div class="search-field"> | |
6 | + <span class="formfield"> | |
7 | + <%= text_field_tag 'q', @q, :title => _("Find profiles"), :style=>"width:85%" %> | |
8 | + </span> | |
9 | + | |
10 | + <%= submit_button(:search, _('Search')) %> | |
11 | + </div> | |
12 | + | |
13 | + <div class="environment-users-results-header"> | |
14 | + <div id='environment-users-filter-title'><%= @title %></div> | |
15 | + | |
16 | + <div id="environment-users-filter-filter"> | |
17 | + <strong><%= _("Filter by: ") %></strong> | |
18 | + | |
19 | + <select id="profile_filter_select"> | |
20 | + <%= options_for_select([['Any', 'any'],["Disabled profiles", "disabled"], ["Enabled profiles", "enabled"]], @filter) %> | |
21 | + </select> | |
22 | + </div> | |
23 | + <div style="clear: both"></div> | |
24 | + </div> | |
25 | + | |
26 | + <table> | |
27 | + <colgroup> | |
28 | + <col width="80%"> | |
29 | + <col width="20%"> | |
30 | + </colgroup> | |
31 | + | |
32 | + <tr> | |
33 | + <th><%= _('Member') %></th> | |
34 | + <th><%= _('Actions') %></th> | |
35 | + </tr> | |
36 | + | |
37 | + <% @collection.each do |p| %> | |
38 | + <tr title="<%= p.name %>"> | |
39 | + <td><%= link_to_profile p.short_name, p.identifier, :title => p.name %> </td> | |
40 | + | |
41 | + <td class='actions'> | |
42 | + <div class="members-buttons-cell"> | |
43 | + <% if p.visible %> | |
44 | + <%= button_without_text :'deactivate-user', _('Deactivate'), {:controller => "profile_editor", :action => 'deactivate_profile', :profile => p.identifier, :id => p.id}, :confirm => _("Do you want to deactivate this profile ?") %> | |
45 | + <% else %> | |
46 | + <%= button_without_text :'activate-user', _('Activate'), {:controller => "profile_editor", :action => 'activate_profile', :profile => p.identifier, :id => p.id}, :confirm => _("Do you want to activate this profile ?") %> | |
47 | + <% end %> | |
48 | + <%= button_without_text :'delete', _('Remove'), {:controller => "profile_editor", :action => 'destroy_profile', :profile => p.identifier, :id => p.id, :return_to => "/admin/admin_panel/manage_organizations_status"}, :method => :post, :confirm => _("Do you want to deactivate this profile ?") %> | |
49 | + </div> | |
50 | + </td> | |
51 | + </tr> | |
52 | + <% end %> | |
53 | + </table> | |
54 | + | |
55 | +<% end %> | |
56 | + | |
57 | +<%= pagination_links @collection, {:param_name => 'npage', :page_links => true} %> | |
58 | + | |
59 | +<% button_bar do %> | |
60 | + <%= button :back, _('Back'), :controller => 'admin_panel' %> | |
61 | +<% end %> | |
62 | + | |
63 | +<script type="text/javascript"> | |
64 | + jQuery(document).ready(function(){ | |
65 | + jQuery("#profile_filter_select").change(function(){ | |
66 | + document.location.href = '/admin/admin_panel/manage_organizations_status?filter='+this.value; | |
67 | + }); | |
68 | + }); | |
69 | +</script> | |
0 | 70 | \ No newline at end of file | ... | ... |
app/views/blocks/my_network.html.erb
1 | 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 | 5 | <ul> |
6 | 6 | <li><%= link_to(_('Homepage'), owner.url, :class => 'url') %></li> |
... | ... | @@ -11,5 +11,5 @@ |
11 | 11 | </ul> |
12 | 12 | |
13 | 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 | 15 | </div> | ... | ... |
app/views/blocks/profile_image.html.erb
app/views/blocks/profile_info.html.erb
app/views/blocks/profile_info_actions/_community.html.erb
0 → 100644
... | ... | @@ -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 @@ |
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 @@ |
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 | -<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 | -<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
app/views/blocks/profile_info_actions/person.html.erb
... | ... | @@ -1,16 +0,0 @@ |
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/box_organizer/_highlights_block.html.erb
1 | +<%= javascript_include_tag "highlight_block" %> | |
2 | + | |
1 | 3 | <strong><%= _('Highlights') %></strong> |
2 | 4 | |
3 | 5 | <table class="noborder"><tbody id="highlights-data-table"> |
4 | 6 | <tr><th><%= _('Image') %></th><th><%= _('Address') %></th><th><%= _('Position') %></th></tr> |
5 | - <% for image in @block.images do %> | |
6 | - <%= highlights_block_config_image_fields @block, image %> | |
7 | + <% @block.images.each_with_index do |image, index| %> | |
8 | + <%= highlights_block_config_image_fields @block, image, index %> | |
7 | 9 | <% end %> |
8 | 10 | </tbody></table> |
9 | 11 | |
10 | -<%= link_to_function(_('New highlight'), nil, :class => 'button icon-add with-text') do |page| | |
11 | - page.insert_html :bottom, 'highlights-data-table', highlights_block_config_image_fields(@block) | |
12 | -end %> | |
12 | +<table class="hidden highlight-table-row"> | |
13 | + <tbody> | |
14 | + <%= highlights_block_config_image_fields(@block) %> | |
15 | + </tbody> | |
16 | +</table> | |
17 | + | |
18 | +<%= link_to(_('New highlight'), '#', :class => 'button icon-add with-text new-highlight-button')%> | |
13 | 19 | |
14 | 20 | <%= labelled_form_field _('Image transition:'), select('block', 'interval', [[_('No automatic transition'), 0]] + [1, 2, 3, 4, 5, 10, 20, 30, 60].map {|item| [n_('Every 1 second', 'Every %d seconds', item) % item, item]}) %> |
15 | 21 | ... | ... |
app/views/catalog/index.html.erb
... | ... | @@ -14,8 +14,8 @@ |
14 | 14 | |
15 | 15 | <ul id="product-list"> |
16 | 16 | <% @products.each do |product| %> |
17 | - <% extra_content = @plugins.dispatch(:catalog_item_extras, product).collect { |content| instance_eval(&content) } %> | |
18 | - <% extra_content_list = @plugins.dispatch(:catalog_list_item_extras, product).collect { |content| instance_eval(&content) } %> | |
17 | + <% extra_content = @plugins.dispatch(:catalog_item_extras, product).collect { |content| instance_exec(&content) } %> | |
18 | + <% extra_content_list = @plugins.dispatch(:catalog_list_item_extras, product).collect { |content| instance_exec(&content) } %> | |
19 | 19 | |
20 | 20 | <% status = [] %> |
21 | 21 | <% status << 'not-available' if !product.available %> | ... | ... |
app/views/categories/_category.html.erb
1 | 1 | <li> |
2 | 2 | <div class='treeitem'> |
3 | - <%= display_color_for_category(category) %> | |
4 | - <%= category.name %> | |
3 | + <% unless category_color_style(category).empty? %> | |
4 | + <span class="color_marker" style="<%= category_color_style(category) %>" ></span> | |
5 | + <% end %> | |
6 | + <span><%= category.name %></span> | |
7 | + | |
5 | 8 | <% if category.children.count > 0 %> |
6 | 9 | <div class='button' id="category-loading-<%= category.id %>" style="position: relative;"> |
7 | 10 | <a href="#" id="show-button-<%= category.id %>" class="show-button" onclick="return false;" data-category="<%= category.id %>"><%= _('Show') %></a> | ... | ... |
app/views/categories/_form.html.erb
1 | +<%= stylesheet_link_tag 'spectrum.css' %> | |
2 | +<%= javascript_include_tag "spectrum.js" %> | |
3 | +<%= javascript_include_tag "colorpicker-noosfero.js" %> | |
4 | + | |
1 | 5 | <%= error_messages_for 'category' %> |
2 | 6 | |
3 | 7 | <%= labelled_form_for 'category', :html => { :multipart => true} do |f| %> |
... | ... | @@ -13,12 +17,13 @@ |
13 | 17 | <% end %> |
14 | 18 | <% end %> |
15 | 19 | |
16 | - <%= select_color_for_category if !environment.enabled?('disable_categories_menu') %> | |
17 | - | |
18 | 20 | <%= required f.text_field('name') %> |
19 | 21 | |
20 | 22 | <%= labelled_check_box(_('Display in the menu'), 'category[display_in_menu]', '1', @category.display_in_menu) %> |
21 | 23 | |
24 | + <%= labelled_colorpicker_field(_('Pick a color'), :category, 'display_color' ) unless environment.enabled?('disable_categories_menu')%> | |
25 | + <span id="color_preview" class = "color_marker" style="<%= category_color_style(@category) %>" ></span> | |
26 | + | |
22 | 27 | <%= f.fields_for :image_builder, @category.image do |i| %> |
23 | 28 | <%= file_field_or_thumbnail(_('Image:'), @category.image, i) %> |
24 | 29 | <% end %> | ... | ... |
app/views/cms/edit.html.erb
... | ... | @@ -31,9 +31,18 @@ |
31 | 31 | |
32 | 32 | <%= select_categories(:article, _('Categorize your article')) %> |
33 | 33 | |
34 | + <br /> | |
35 | + | |
34 | 36 | <%= f.text_field('tag_list', :size => 64) %> |
35 | 37 | <%= content_tag( 'small', _('Separate tags with commas') ) %> |
36 | 38 | |
39 | + <script> | |
40 | + jQuery('#article_tag_list').inputosaurus({ | |
41 | + autoCompleteSource: <%= "'/myprofile/#{profile.identifier}/cms/search_tags'," %> | |
42 | + activateFinalResult : true | |
43 | + }) | |
44 | + </script> | |
45 | + | |
37 | 46 | <div id='edit-article-options'> |
38 | 47 | <%= options_for_article(@article, @tokenized_children) %> |
39 | 48 | </div> | ... | ... |
app/views/comment/_comment_form.html.erb
... | ... | @@ -31,7 +31,7 @@ function check_captcha(button, confirm_action) { |
31 | 31 | return true; |
32 | 32 | <% else %> |
33 | 33 | jQuery('#recaptcha-container').show(); |
34 | - jQuery.colorbox({ inline : true, href : '#recaptcha-container', maxWidth : '600px', maxHeight : '300px' }); | |
34 | + jQuery.colorbox({ html: jQuery('#recaptcha-container').html(), maxWidth : '600px', maxHeight : '300px' }); | |
35 | 35 | jQuery('#confirm-captcha').unbind('click'); |
36 | 36 | jQuery('#confirm-captcha').bind('click', function() { |
37 | 37 | jQuery.colorbox.close(); | ... | ... |
app/views/content_viewer/article_versions.html.erb
1 | 1 | <div class="article-versions"> |
2 | - <%= button(:back, _('Go back to latest version'), {:action => 'view_page'}) %> | |
2 | + <%= button(:back, _('Go back to latest version'), @page.url) %> | |
3 | 3 | </div> |
4 | 4 | |
5 | 5 | <%= article_title(@page, :no_link => true) %> |
6 | 6 | |
7 | 7 | <p><%= _('This is the list of all versions of this content. Select a version to see it and then revert to it.') %>.</p> |
8 | 8 | |
9 | -<%= form_tag({:controller => 'content_viewer', :action => 'versions_diff', :profile => profile.identifier, :page => @page.path.split('/')}, :method => 'get') do %> | |
9 | +<%= form_tag({:controller => 'content_viewer', :action => 'versions_diff', :profile => profile.identifier, :page => @page.path}, :method => 'get') do %> | |
10 | 10 | <ul id="article-versions"> |
11 | 11 | <% @versions.each do |v| %> |
12 | 12 | <li> | ... | ... |
app/views/content_viewer/blog_page.html.erb
... | ... | @@ -9,13 +9,15 @@ |
9 | 9 | </div> |
10 | 10 | <hr class="pre-posts"/> |
11 | 11 | <div class="blog-posts"> |
12 | + <% paginate = true %> | |
12 | 13 | <%= |
13 | 14 | posts = @posts |
14 | 15 | format = blog.visualization_format |
15 | 16 | if inside_block |
16 | 17 | posts = blog.posts.paginate(:page=>1, :per_page=>inside_block.posts_per_page) |
17 | 18 | format = inside_block.visualization_format |
19 | + paginate = false | |
18 | 20 | end |
19 | - (blog.empty? ? content_tag('em', _('(no posts)')) : list_posts(posts, format)) | |
21 | + (blog.empty? ? content_tag('em', _('(no posts)')) : list_posts(posts, format, paginate)) | |
20 | 22 | %> |
21 | 23 | </div> | ... | ... |
app/views/content_viewer/folder.html.erb
app/views/content_viewer/versioned_article.html.erb
... | ... | @@ -23,7 +23,6 @@ |
23 | 23 | <p id="no-current-version"> |
24 | 24 | <%= _('This is not the latest version of this content.') %> |
25 | 25 | </p> |
26 | -</div> | |
27 | 26 | |
28 | 27 | <% version_license = @page.version_license(@version) %> |
29 | 28 | <%# This seemingly doubled verification exists because the article-sub-header | ... | ... |
app/views/content_viewer/view_page.html.erb
app/views/events/_month.html.erb
... | ... | @@ -13,8 +13,8 @@ |
13 | 13 | date.day, |
14 | 14 | :url => {:action => 'events_by_day', :year => date.year, :month => date.month, :day => date.day, :category_id => @category_id}, |
15 | 15 | :update => 'events-of-the-day', |
16 | - :loading => '$("events-of-the-day").addClassName("loading")', | |
17 | - :complete => '$("events-of-the-day").removeClassName("loading")' | |
16 | + :loading => "$('events-of-the-day').addClassName('loading')", | |
17 | + :complete => "$('events-of-the-day').removeClassName('loading')" | |
18 | 18 | ) : |
19 | 19 | date.day |
20 | 20 | %> | ... | ... |
app/views/features/index.html.erb
... | ... | @@ -37,6 +37,18 @@ Check all the features you want to enable for your environment, uncheck all the |
37 | 37 | <%= select_organization_approval_method('environment', 'organization_approval_method') %> |
38 | 38 | <hr/> |
39 | 39 | |
40 | +<h3><%= _('Members Whitelist') %></h3> | |
41 | + <div class="option"> | |
42 | + <%= check_box :environment, :members_whitelist_enabled %> | |
43 | + <label><%= _('Enable whitelist') %></label> | |
44 | + </div> | |
45 | + <div class="input"> | |
46 | + <div class="info"><%= _('Allow these people to access this environment:') %></div> | |
47 | + <% tokenized_members = prepare_to_token_input(environment.people.find(:all, :conditions => {:id => environment.members_whitelist})) %> | |
48 | + <%= token_input_field_tag('environment[members_whitelist]', 'search-members', {:action => 'search_members'}, {:focus => false, :hint_text => _('Type in a search term for a user'), :pre_populate => tokenized_members}) %> | |
49 | + </div> | |
50 | +<hr/> | |
51 | + | |
40 | 52 | <div> |
41 | 53 | <% button_bar do %> |
42 | 54 | <%= submit_button('save', _('Save changes')) %> | ... | ... |