Commit cd4eff3c40cb9834e9a7673f3b4b2bc02f9d1036
Exists in
staging
and in
4 other branches
Merge branch 'staging' into security-search
Showing
1968 changed files
with
192212 additions
and
85052 deletions
Show diff stats
Too many changes.
To preserve performance only 100 of 1968 files displayed.
... | ... | @@ -0,0 +1,26 @@ |
1 | +before_script: | |
2 | + - mkdir -p tmp/pids log | |
3 | + - bundle check || bundle install | |
4 | +# workaround for plugins with Gemfile | |
5 | + - perl -pi -e 's/--local //' script/noosfero-plugins | |
6 | + - script/noosfero-plugins disableall | |
7 | + - bundle exec rake makemo &>/dev/null | |
8 | +# database | |
9 | + - cp config/database.yml.gitlab-ci config/database.yml | |
10 | + - createdb gitlab_ci_test || true | |
11 | + - bundle exec rake db:schema:load &>/dev/null | |
12 | + - bundle exec rake db:migrate &>/dev/null | |
13 | + | |
14 | +units: | |
15 | + script: bundle exec rake test:units | |
16 | +functionals: | |
17 | + script: bundle exec rake test:functionals | |
18 | +integration: | |
19 | + script: bundle exec rake test:integration | |
20 | +cucumber: | |
21 | + script: bundle exec rake cucumber | |
22 | +selenium: | |
23 | + script: bundle exec rake selenium | |
24 | +plugins: | |
25 | + script: bundle exec rake test:noosfero_plugins | |
26 | + | ... | ... |
... | ... | @@ -0,0 +1,39 @@ |
1 | +[submodule "plugins/pairwise"] | |
2 | + path = plugins/pairwise | |
3 | + url = https://gitlab.com/noosfero-plugins/pairwise.git | |
4 | +[submodule "plugins/proposals_discussion"] | |
5 | + path = plugins/proposals_discussion | |
6 | + url = https://gitlab.com/noosfero-plugins/proposals_discussion.git | |
7 | +[submodule "plugins/site_tour"] | |
8 | + path = plugins/site_tour | |
9 | + url = https://gitlab.com/noosfero-plugins/site_tour.git | |
10 | +[submodule "plugins/gamification"] | |
11 | + path = plugins/gamification | |
12 | + url = https://gitlab.com/noosfero-plugins/gamification.git | |
13 | +[submodule "plugins/comment_paragraph"] | |
14 | + path = plugins/comment_paragraph | |
15 | + url = https://gitlab.com/noosfero-plugins/comment-paragraph.git | |
16 | +[submodule "plugins/notification"] | |
17 | + path = plugins/notification | |
18 | + url = https://gitlab.com/noosfero-plugins/notification.git | |
19 | +[submodule "plugins/email_article"] | |
20 | + path = plugins/email_article | |
21 | + url = https://gitlab.com/noosfero-plugins/email_article.git | |
22 | +[submodule "public/proposal-app"] | |
23 | + path = public/proposal-app | |
24 | + url = https://gitlab.com/participa/proposal-app.git | |
25 | +[submodule "plugins/gravatar_provider"] | |
26 | + path = plugins/gravatar_provider | |
27 | + url = https://gitlab.com/noosfero-plugins/gravatar-provider.git | |
28 | +[submodule "plugins/juventude"] | |
29 | + path = plugins/juventude | |
30 | + url = https://gitlab.com/noosfero-plugins/juventude.git | |
31 | +[submodule "plugins/dialoga"] | |
32 | + path = plugins/dialoga | |
33 | + url = https://gitlab.com/participa/dialoga-plugin.git | |
34 | +[submodule "rest-clients/confjuvapp"] | |
35 | + path = rest-clients/confjuvapp | |
36 | + url = https://gitlab.com/participa/confjuvapp.git | |
37 | +[submodule "rest-clients/proposal-app"] | |
38 | + path = rest-clients/proposal-app | |
39 | + url = https://gitlab.com/participa/proposal-app.git | ... | ... |
... | ... | @@ -0,0 +1,53 @@ |
1 | +language: ruby | |
2 | +rvm: | |
3 | +# for 2.2 support we need to upgrade the pg gem | |
4 | + - 2.1.6 | |
5 | + | |
6 | +sudo: false | |
7 | +addons: | |
8 | + apt: | |
9 | + packages: | |
10 | + - po4a | |
11 | + - iso-codes | |
12 | + - tango-icon-theme | |
13 | + - pidgin-data | |
14 | + # for gem extensions | |
15 | + - libmagickwand-dev | |
16 | + - libpq-dev | |
17 | + - libreadline-dev | |
18 | + - libsqlite3-dev | |
19 | + - libxslt1-dev | |
20 | + | |
21 | +before_install: | |
22 | + - gem env | |
23 | + | |
24 | +# workaround for https://github.com/travis-ci/travis-ci/issues/4536 | |
25 | +before_install: | |
26 | + - export GEM_HOME=$PWD/vendor/bundle/ruby/2.1.0 | |
27 | + - gem install bundler | |
28 | +cache: bundler | |
29 | + | |
30 | +before_script: | |
31 | + - mkdir -p tmp/pids log | |
32 | +# workaround for plugins with Gemfile | |
33 | + - perl -pi -e 's/cat .+ > \$gemfile/echo "source \\"https:\/\/rubygems.org\\"" > \$gemfile && cat \$source\/Gemfile >> \$gemfile/' script/noosfero-plugins | |
34 | + - perl -pi -e 's/--local --quiet/install --jobs=3 --retry=3/' script/noosfero-plugins | |
35 | + - script/noosfero-plugins disableall | |
36 | + - bundle exec rake makemo &>/dev/null | |
37 | +# database | |
38 | + - cp config/database.yml.travis config/database.yml | |
39 | + - psql -c 'create database myapp_test;' -U postgres | |
40 | + - bundle exec rake db:schema:load &>/dev/null | |
41 | + - bundle exec rake db:migrate &>/dev/null | |
42 | + | |
43 | +env: | |
44 | + - TASK=test:units | |
45 | + - TASK=test:functionals | |
46 | + - TASK=test:integration | |
47 | + - TASK=cucumber | |
48 | + - TASK=selenium | |
49 | + - TASK=test:noosfero_plugins | |
50 | + | |
51 | +script: | |
52 | + - bundle exec rake $TASK | |
53 | + | ... | ... |
AUTHORS.md
1 | +This list is automatically generated at release time. Please do not change it. | |
2 | + | |
1 | 3 | If you are not listed here, but should be, please write to the noosfero mailing |
2 | 4 | list: http://listas.softwarelivre.org/cgi-bin/mailman/listinfo/noosfero-dev |
3 | 5 | (this list requires subscription to post, but since you are an author of |
... | ... | @@ -8,256 +10,120 @@ Developers |
8 | 10 | |
9 | 11 | Ábner Silva de Oliveira <abner.oliveira@serpro.gov.br> |
10 | 12 | Alan Freihof Tygel <alantygel@gmail.com> |
11 | -alcampelo <alcampelo@alcampelo.(none)> | |
12 | 13 | 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 | -analosnak <analosnak@gmail.com> | |
14 | +Alex Campelo <campelo.al1@gmail.com> | |
15 | +Álvaro Fernando <alvarofernandoms@gmail.com> | |
44 | 16 | Ana Losnak <analosnak@gmail.com> |
45 | -Andre Bernardes <andrebsguedes@gmail.com> | |
46 | -Antonio Terceiro + Carlos Morais <terceiro@colivre.coop.br> | |
47 | -Antonio Terceiro + Paulo Meirelles <terceiro@colivre.coop.br> | |
17 | +Ana Paula Vargas <anapaulavnoronha@gmail.com> | |
18 | +Andre Bedran <bedran.fleck@gmail.com> | |
19 | +André Guedes <andrebsguedes@gmail.com> | |
20 | +Andrey Aleksanyants <aaleksanyants@yahoo.com> | |
48 | 21 | Antonio Terceiro <terceiro@colivre.coop.br> |
49 | 22 | Arthur Del Esposte <arthurmde@gmail.com> |
50 | -Arthur Del Esposte <arthurmde@yahoo.com.br> | |
23 | +Athos Ribeiro <athoscribeiro@gmail.com> | |
51 | 24 | Aurelio A. Heckert <aurelio@colivre.coop.br> |
52 | -Braulio Bhavamitra <brauliobo@gmail.com> | |
53 | -Bráulio Bhavamitra <brauliobo@gmail.com> | |
54 | 25 | Braulio Bhavamitra <braulio@eita.org.br> |
55 | -Caio <caio.csalgado@gmail.com> | |
56 | -Caio + Diego + Pedro + João <caio.csalgado@gmail.com> | |
26 | +Brenddon Gontijo <brenddongontijo@msn.com> | |
57 | 27 | Caio Formiga <caio.formiga@gmail.com> |
58 | -Caio, Pedro <caio.csalgado@gmail.com> | |
59 | -Caio Salgado + Alessandro Palmeira <caio.csalgado@gmail.com> | |
60 | 28 | Caio Salgado <caio.csalgado@gmail.com> |
61 | -Caio Salgado + Carlos Morais + Diego Araújo + Pedro Leal <diegoamc90@gmail.com> | |
62 | -Caio Salgado + Diego Araujo <caio.csalgado@gmail.com> | |
63 | -Caio Salgado + Diego Araújo <caio.csalgado@gmail.com> | |
64 | -Caio Salgado + Diego Araújo <diegoamc90@gmail.com> | |
65 | -Caio Salgado + Diego Araújo + Jefferson Fernandes <caio.csalgado@gmail.com> | |
66 | -Caio Salgado + Diego Araújo + João M. M. da Silva <caio.csalgado@gmail.com> | |
67 | -Caio Salgado + Diego Araújo + Pedro Leal <caio.csalgado@gmail.com> | |
68 | -Caio Salgado + Diego Araújo + Pedro Leal <diegoamc90@gmail.com> | |
69 | -Caio Salgado + Diego Araújo + Rafael Manzo <diegoamc90@gmail.com> | |
70 | -Caio Salgado + Jefferson Fernandes <caio.csalgado@gmail.com> | |
71 | -Caio Salgado + Jefferson Fernandes <jeffs.fernandes@gmail.com> | |
72 | -Caio Salgado + Rafael Manzo <caio.csalgado@gmail.com> | |
73 | -Caio Salgado + Renan Teruo <caio.csalgado@gmail.com> | |
74 | -Caio Salgado + Renan Teruo <caio.salgado@gmail.com> | |
75 | -Caio Salgado + Renan Teruo + Jefferson Fernandes <jeffs.fernandes@gmail.com> | |
76 | -Caio Salgado + Renan Teruo <renanteruoc@gmail.com> | |
77 | 29 | Caio SBA <caio@colivre.coop.br> |
78 | 30 | Caio Tiago Oliveira <caiotiago@colivre.coop.br> |
79 | 31 | Carlos Andre de Souza <carlos.andre.souza@msn.com> |
80 | 32 | Carlos Morais <carlos88morais@gmail.com> |
81 | -Carlos Morais + Diego Araújo <diegoamc90@gmail.com> | |
82 | -Carlos Morais + Eduardo Morais <carlos88morais@gmail.com> | |
83 | -Carlos Morais + Paulo Meirelles <carlos88morais@gmail.com> | |
84 | -Carlos Morais + Pedro Leal <carlos88morais@gmail.com> | |
85 | -Daniel Alves + Diego Araújo <danpaulalves@gmail.com> | |
86 | -Daniel Alves + Diego Araújo <diegoamc90@gmail.com> | |
87 | -Daniel Alves + Diego Araújo + Guilherme Rojas <danpaulalves@gmail.com> | |
88 | -Daniel Alves + Diego Araújo + Guilherme Rojas <diegoamc90@gmail.com> | |
89 | -Daniel Alves + Diego Araújo + Guilherme Rojas <guilhermehrojas@gmail.com> | |
90 | -Daniel Alves + Guilherme Rojas <danpaulalves@gmail.com> | |
91 | -Daniel Alves + Rafael Manzo <rr.manzo@gmail.com> | |
33 | +Christophe DANIEL <papaeng@gmail.com> | |
34 | +Daniela Feitosa <alessandro.palmeira@gmail.com> | |
35 | +Daniel Alves <danpaulalves@gmail.com> | |
92 | 36 | Daniela Soares Feitosa <danielafeitosa@colivre.coop.br> |
93 | 37 | Daniel Bucher <daniel.bucher88@gmail.com> |
94 | 38 | Daniel Cunha <daniel@colivre.coop.br> |
39 | +Daniel Tygel <dtygel@eita.org.br> | |
95 | 40 | David Carlos <ddavidcarlos1392@gmail.com> |
96 | -diegoamc <diegoamc90@gmail.com> | |
97 | -Diego Araújo + Alessandro Palmeira <diegoamc90@gmail.com> | |
98 | -Diego Araújo + Alessandro Palmeira + João M. M. da Silva <diegoamc90@gmail.com> | |
99 | -Diego Araújo + Alessandro Palmeira + Rafael Manzo <rr.manzo@gmail.com> | |
100 | -Diego Araujo + Caio Salgado <diegoamc90@gmail.com> | |
101 | -Diego Araújo + Daniel Alves + Rafael Manzo <rr.manzo@gmail.com> | |
102 | -Diego Araújo <diegoamc90@gmail.com> | |
103 | -Diego Araújo + Eduardo Morais + Paulo Meirelles <diegoamc90@gmail.com> | |
104 | -Diego Araújo + Guilherme Rojas <diegoamc90@gmail.com> | |
105 | -Diego Araújo + Jefferson Fernandes <diegoamc90@gmail.com> | |
106 | -Diego Araujo + Jefferson Fernandes <jeffs.fernandes@gmail.com> | |
107 | -Diego Araújo + João Machini <diegoamc90@gmail.com> | |
108 | -Diego Araújo + João Machini <digoamc90@gmail.com> | |
109 | -Diego Araújo + João M. M. da Silva + Alessandro Palmeira <jaodsilv@linux.ime.usp.br> | |
110 | -Diego Araújo + João M. M. da Silva <diegoamc90@gmail.com> | |
111 | -Diego Araújo + João M. M. da Silva + João Machini <diegoamc90@gmail.com> | |
112 | -Diego Araújo + João M. M. da Silva + Pedro Leal <diegoamc90@gmail.com> | |
113 | -Diego Araújo + Paulo Meirelles <diegoamc90@gmail.com> | |
114 | -Diego Araújo + Pedro Leal <diegoamc90@gmail.com> | |
115 | -Diego Araujo + Rafael Manzo <diegoamc90@gmail.com> | |
116 | -Diego Araújo + Rafael Manzo <diegoamc90@gmail.com> | |
117 | -Diego Araújo + Renan Teruo + Alessandro Palmeira <diegoamc90@gmail.com> | |
118 | -Diego Araújo + Renan Teruo <diegoamc90@gmail.com> | |
119 | -Diego Araujo + Rodrigo Souto + Rafael Manzo <rr.manzo@gmail.com> | |
120 | -Diego + Jefferson <diegoamc90@gmail.com> | |
121 | -Diego Martinez <diegoamc90@gmail.com> | |
122 | -Diego + Renan <renanteruoc@gmail.com> | |
123 | -DylanGuedes <djmgguedes@gmail.com> | |
124 | -Eduardo Passos <eduardo@risa.localdomain.localhost> | |
41 | +Diego Araujo <diegoamc90@gmail.com> | |
42 | +Dylan Guedes <djmgguedes@gmail.com> | |
43 | +Eduardo Morais | |
125 | 44 | Eduardo Passos <eduardosteps@gmail.com> |
126 | 45 | Eduardo Tourinho Edington <eduardo.edington@serpro.gov.br> |
127 | -Evandro Jr <evandrojr@gmail.com> | |
128 | -Evandro Junior <evandrojr@gmail.com> | |
46 | +Eduardo Vital <vitaldu@gmail.com> | |
47 | +Evandro Magalhaes Leite Junior <evandro.leite@serpro.gov.br> | |
129 | 48 | Fabio Teixeira <fabio1079@gmail.com> |
130 | 49 | FAMMA TV NOTICIAS MEDIOS DE CO <revistafammatvmusic.oficial@gmail.com> |
131 | 50 | Fernanda Lopes <nanda.listas+psl@gmail.com> |
132 | -Francisco Marcelo A. Lima Júnior <francisco.lima-junior@serpro.gov.br> | |
133 | -Francisco Marcelo de Araujo Lima Junior <79350259591@serpro-1457614.(none)> | |
51 | +Filipe Ribeiro <firibeiro77@live.com> | |
134 | 52 | Francisco Marcelo de Araújo Lima Júnior <francisco.lima-junior@serpro.gov.br> |
135 | -Francisco Marcelo de Araújo Lima Júnior <maljunior@gmail.com> | |
136 | 53 | Gabriela Navarro <navarro1703@gmail.com> |
137 | 54 | Gonzalo Exequiel Pedone <hipersayan.x@gmail.com> |
138 | 55 | Grazieno Pellegrino <grazieno@gmail.com> |
139 | -Gust <darksshades@hotmail.com> | |
56 | +Guilherme C. Muniz <guilherme.cmuniz@gmail.com> | |
57 | +Guilherme Rojas <guilhermehrojas@gmail.com> | |
58 | +Gustavo Jaruga <darksshades@gmail.com> | |
140 | 59 | Hebert Douglas <hebertdougl@gmail.com> |
141 | 60 | Hugo Melo <hugo@riseup.net> |
61 | +Iolane Andrade <andrade.icaa@gmail.com> | |
142 | 62 | Isaac Canan <isaac@intelletto.com.br> |
143 | 63 | Italo Valcy <italo@dcc.ufba.br> |
144 | -Jefferson Fernandes + Diego Araujo + Rafael Manzo <jeffs.fernandes@gmail.com> | |
145 | -Jefferson Fernandes + Joao M. M. da Silva <jeffs.fernandes@gmail.com> | |
146 | -Jefferson Fernandes + Joao M. M. Silva <jeffs.fernandes@gmail.com> | |
147 | -João da Silva + Eduardo Morais + Rafael Manzo <rr.manzo@gmail.com> | |
148 | -João da Silva <jaodsilv@linux.ime.usp.br> | |
149 | -João Marco Maciel da Silva + Rafael Manzo + Renan Teruo <jaodsilv@linux.ime.usp.br> | |
150 | -João M. M. da Silva + Alessandro Palmeira + Diego Araújo + Caio Salgado <jaodsilv@linux.ime.usp.br> | |
151 | -João M. M. da Silva + Alessandro Palmeira + Diego Araújo <jaodsilv@linux.ime.usp.br> | |
152 | -Joao M. M. da Silva + Alessandro Palmeira <jaodsilv@linux.ime.usp.br> | |
153 | -João M. M. da Silva + Alessandro Palmeira <jaodsilv@linux.ime.usp.br> | |
154 | -João M. M. da Silva + Alessandro Palmeira + João Machini <jaodsilv@linux.ime.usp.br> | |
155 | -João M. M. da Silva + Caio Salgado + Alessandro Palmeira <jaodsilv@linux.ime.usp.br> | |
156 | -João M. M. da Silva + Caio Salgado <jaodsilv@linux.ime.usp.br> | |
157 | -João M. M. da Silva + Carlos Morais <jaodsilv@linux.ime.usp.br> | |
158 | -João M. M. da Silva + Diego Araújo <diegoamc90@gmail.com> | |
159 | -João M. M. da Silva + Diego Araújo <jaodsilv@linux.ime.usp.br> | |
160 | -João M. M. da Silva + Diego Araújo + Pedro Leal <jaodsilv@linux.ime.usp.br> | |
64 | +Jefferson Fernandes <jeffs.fernandes@gmail.com> | |
65 | +Jérôme Jutteau <j.jutteau@gmail.com> | |
66 | +João Machini | |
161 | 67 | João M. M. da Silva <jaodsilv@linux.ime.usp.br> |
162 | -Joao M. M. da Silva + Jefferson Fernandes <jaodsilv@linux.ime.usp.br> | |
163 | -João M. M. da Silva + Jefferson Fernandes <jaodsilv@linux.ime.usp.br> | |
164 | -João M. M. da Silva + João M. Miranda <jaodsilv@linux.ime.usp.br> | |
165 | -João M. M. da Silva + Paulo Meirelles <jaodsilv@linux.ime.usp.br> | |
166 | -João M. M. da Silva + Pedro Leal <jaodsilv@linux.ime.usp.br> | |
167 | -João M. M. da Silva + Rafael Manzo + Diego Araújo <jaodsilv@linux.ime.usp.br> | |
168 | -João M. M. da Silva + Rafael Manzo <jaodsilv@linux.ime.usp.br> | |
169 | -João M. M. da Silva + Renan Teruo <jaodsilv@linux.ime.usp.br> | |
170 | -João M. M. Silva + Caio Salgado <jaodsilv@linux.ime.usp.br> | |
171 | -João M. M. Silva + Diego Araújo <jaodsilv@linux.ime.usp.br> | |
172 | -Joao M. M. Silva + Jefferson Fernandes <jaodsilv@linux.ime.usp.br> | |
173 | -João M. M. Silva + Paulo Meirelles <jaodsilv@linux.ime.usp.br> | |
174 | -João M. M. Silva + Rafael Manzo <jaodsilv@linux.ime.usp.br> | |
175 | -João M. M. Silva + Renan Teruo <jaodsilv@linux.ime.usp.br> | |
176 | 68 | Joenio Costa <joenio@colivre.coop.br> |
177 | 69 | Josef Spillner <josef.spillner@tu-dresden.de> |
178 | 70 | Jose Pedro <1jpsneto@gmail.com> |
179 | -Junior Silva <junior@bajor.localhost.localdomain> | |
180 | -Junior Silva <junior@sedeantigo.colivre.coop.br> | |
181 | 71 | Junior Silva <juniorsilva1001@gmail.com> |
182 | -Junior Silva <juniorsilva7@juniorsilva-Aspire-5750Z.(none)> | |
183 | -Junior Silva <juniorsilva@colivre.coop.br> | |
184 | -juniorsilva <juniorsilva@QonoS.localhost.localdomain> | |
185 | 72 | Keilla Menezes <keilla@colivre.coop.br> |
186 | 73 | Larissa Reis <larissa@colivre.coop.br> |
187 | -Larissa Reis <reiss.larissa@gmail.com> | |
188 | 74 | Leandro Alves <leandrosustenido@gmail.com> |
189 | -Leandro Nunes dos Santos <81665687568@serpro-1541727.Home> | |
190 | -Leandro Nunes dos Santos <81665687568@serpro-1541727.(none)> | |
191 | -Leandro Nunes dos Santos <leandronunes@gmail.com> | |
192 | 75 | Leandro Nunes dos Santos <leandro.santos@serpro.gov.br> |
76 | +Leandro Veloso <leandrovelosorodrigues@gmail.com> | |
193 | 77 | LinguÁgil 2010 <linguagil.bahia@gmail.com> |
78 | +Lucas Couto <loc.unb@gmail.com> | |
194 | 79 | Lucas Kanashiro <kanashiro.duarte@gmail.com> |
195 | -Lucas Melo <lucas@colivre.coop.br> | |
196 | 80 | Lucas Melo <lucaspradomelo@gmail.com> |
197 | -Luciano <lucianopcbr@gmail.com> | |
198 | 81 | Luciano Prestes Cavalcanti <lucianopcbr@gmail.com> |
199 | 82 | Luis David Aguilar Carlos <ludwig9003@gmail.com> |
200 | 83 | Luiz Fernando de Freitas Matos <luiz@luizff.matos@gmail.com> |
201 | -Marcos <marcos.rpj2@gmail.com> | |
84 | +Luiz Matos <luizff.matos@gmail.com> | |
202 | 85 | Marcos Ramos <ms.ramos@outlook.com> |
86 | +Marcos Ronaldo <marcos.rpj2@gmail.com> | |
87 | +Mariel Zasso <noosfero-br@listas.softwarelivre.org> | |
203 | 88 | Martín Olivera <molivera@solar.org.ar> |
89 | +Matheus Faria <matheus.sousa.faria@gmail.com> | |
204 | 90 | Maurilio Atila <cabelotaina@gmail.com> |
205 | 91 | M for Momo <mo@rtnp.org> |
206 | 92 | Michal Čihař <michal@cihar.com> |
93 | +Michel Felipe <mfelipeof@gmail.com> | |
207 | 94 | Moises Machado <moises@colivre.coop.br> |
208 | 95 | Naíla Alves <naila@colivre.coop.br> |
209 | 96 | Nanda Lopes <nanda.listas+psl@gmail.com> |
210 | 97 | Niemand Jedermann <predatorix@web.de> |
211 | 98 | Parley Martins <parleypachecomartins@gmail.com> |
212 | -Paulo Meirelles + Alessandro Palmeira + João M. M. da Silva <paulo@softwarelivre.org> | |
213 | -Paulo Meirelles + Alessandro Palmeira <paulo@softwarelivre.org> | |
214 | -Paulo Meirelles + Carlos Morais <paulo@softwarelivre.org> | |
215 | -Paulo Meirelles + Diego Araújo <paulo@softwarelivre.org> | |
216 | -Paulo Meirelles + João M. M. da Silva <paulo@softwarelivre.org> | |
217 | 99 | Paulo Meirelles <paulo@softwarelivre.org> |
218 | -Paulo Meirelles + Rafael Manzo <paulo@softwarelivre.org> | |
100 | +Pedro de Lyra <pedrodelyra@gmail.com> | |
101 | +Pedro Leal | |
102 | +Rafael de Souza Queiroz <querafael@live.com> | |
219 | 103 | Rafael Gomes <rafaelgomes@techfree.com.br> |
220 | -Rafael Manzo + Alessandro Palmeira <rr.manzo@gmail.com> | |
221 | -Rafael Manzo + Daniel Alves <danpaulalves@gmail.com> | |
222 | -Rafael Manzo + Diego Araújo <rr.manzo@gmail.com> | |
223 | -Rafael Manzo + João M. M. Silva <rr.manzo@gmail.com> | |
224 | -Rafael Manzo + Paulo Meirelles <rr.manzo@gmail.com> | |
225 | 104 | Rafael Martins <rmmartins@gmail.com> |
226 | -Rafael Reggiani Manzo + Caio Salgado + Jefferson Fernandes <rr.manzo@gmail.com> | |
227 | -Rafael Reggiani Manzo + Diego Araujo <diegoamc90@gmail.com> | |
228 | -Rafael Reggiani Manzo + Diego Araujo <rr.manzo@gmail.com> | |
229 | -Rafael Reggiani Manzo + Diego Araújo <rr.manzo@gmail.com> | |
230 | -Rafael Reggiani Manzo + João M. M. da Silva <rr.manzo@gmail.com> | |
231 | 105 | Rafael Reggiani Manzo <rr.manzo@gmail.com> |
232 | 106 | Raphaël Rousseau <raph@r4f.org> |
233 | 107 | Raquel Lira <raquel.lira@gmail.com> |
234 | 108 | Raquel <rcordioli@gmail.com> |
235 | -Renan Teruo + Caio Salgado <renanteruoc@gmail.com> | |
236 | -Renan Teruoc + Diego Araujo <renanteruoc@gmail.com> | |
237 | -Renan Teruo + Diego Araujo <renanteruoc@gmail.com> | |
238 | -Renan Teruo + Diego Araújo <renanteruoc@gmail.com> | |
239 | -Renan Teruo + Paulo Meirelles <renanteruoc@gmail.com> | |
240 | -Renan Teruo + Rafael Manzo <renanteruoc@gmail.com> | |
241 | -Rodrigo Souto + Ana Losnak + Daniel Bucher + Caio Almeida + Leandro Nunes + Daniela Feitosa + Mariel Zasso <noosfero-br@listas.softwarelivre.org> | |
109 | +Renan Costa <renan2727@hotmail.com> | |
110 | +Renan Teruo <renanteruoc@gmail.com> | |
111 | +Rodrigo Medeiros <rodrigo.mss01@gmail.com> | |
242 | 112 | Rodrigo Souto <rodrigo@colivre.coop.br> |
243 | 113 | Ronny Kursawe <kursawe.ronny@googlemail.com> |
244 | -root <root@debian.sdr.serpro> | |
245 | 114 | Samuel R. C. Vale <srcvale@holoscopio.com> |
246 | -Tallys Martins <tallysmartins@gmail.com> | |
247 | 115 | Tallys Martins <tallysmartins@yahoo.com.br> |
248 | -tallys <tallys@tallys> | |
249 | -tallys <tallys@tallys.(none)> | |
116 | +Thiago Casotti <thiago.casotti@uol.com.br> | |
117 | +Thiago Kairala <thiagor.kairala@gmail.com> | |
118 | +Thiago Ribeiro <thiagitosouza@hotmail.com> | |
250 | 119 | Thiago Zoroastro <thiago.zoroastro@bol.com.br> |
251 | 120 | Tuux <tuxa@galaxie.eu.org> |
121 | +TWS <tablettws@gmail.com> | |
252 | 122 | Valessio Brito <contato@valessiobrito.com.br> |
253 | -Valessio Brito <contato@valessiobrito.info> | |
254 | -Valessio Brito <valessio@gmail.com> | |
255 | -vfcosta <vfcosta@gmail.com> | |
256 | -Victor Carvalho <victorhugodf.ac@gmail.com> | |
257 | 123 | Victor Costa <vfcosta@gmail.com> |
258 | 124 | Victor Hugo Alves de Carvalho <victorhugodf.ac@gmail.com> |
259 | 125 | Vinicius Cubas Brand <viniciuscb@gmail.com> |
260 | -Visita <visita@debian.(none)> | |
126 | +Wilton Rodrigues <braynwilton@gmail.com> | |
261 | 127 | Yann Lugrin <yann.lugrin@liquid-concept.ch> |
262 | 128 | |
263 | 129 | Ideas, specifications and incentive | ... | ... |
Gemfile
1 | 1 | source "https://rubygems.org" |
2 | -gem 'rails', '~> 3.2.21' | |
2 | +gem 'rails', '~> 3.2.22' | |
3 | 3 | gem 'minitest', '~> 3.2.0' |
4 | 4 | gem 'fast_gettext', '~> 0.6.8' |
5 | 5 | gem 'acts-as-taggable-on', '~> 3.4.2' |
... | ... | @@ -11,27 +11,46 @@ gem 'will_paginate', '~> 3.0.3' |
11 | 11 | gem 'ruby-feedparser', '~> 0.7' |
12 | 12 | gem 'daemons', '~> 1.1.5' |
13 | 13 | gem 'thin', '~> 1.3.1' |
14 | -gem 'nokogiri', '~> 1.5.5' | |
14 | +gem 'nokogiri', '~> 1.6.0' | |
15 | 15 | gem 'rake', :require => false |
16 | 16 | gem 'rest-client', '~> 1.6.7' |
17 | 17 | gem 'exception_notification', '~> 4.0.1' |
18 | 18 | gem 'gettext', '~> 2.2.1', :require => false |
19 | 19 | gem 'locale', '~> 2.0.5' |
20 | 20 | gem 'whenever', :require => false |
21 | -gem 'eita-jrails', '>= 0.9.5', :require => 'jrails' | |
21 | +gem 'eita-jrails', '~> 0.9.5', require: 'jrails' | |
22 | 22 | |
23 | -group :assets do | |
24 | - gem 'uglifier', '>= 1.0.3' | |
25 | - gem 'sass-rails' | |
26 | -end | |
23 | +# API dependencies | |
24 | +gem 'grape', '~> 0.12' | |
25 | +gem 'grape-entity' | |
26 | +#FIXME Get the Grape Loggin from master yo solve this issue https://github.com/intridea/grape/issues/1059 | |
27 | +#We have to remove this commit referenve code when update the next release of grape_logging. Actualy we are using (1.1.2) | |
28 | +gem 'grape_logging', :git => 'https://github.com/aceunreal/grape_logging.git', :ref => 'f1755ae' | |
29 | +gem 'rack-cors' | |
30 | +gem 'rack-contrib' | |
31 | +gem 'liquid', '~> 3.0.3' | |
32 | +#gem 'grape-swagger-rails' | |
33 | +gem 'rubyzip' | |
34 | + | |
35 | +gem 'execjs' | |
36 | +gem 'therubyracer' | |
37 | + | |
38 | +# FIXME list here all actual dependencies (i.e. the ones in debian/control), | |
39 | +# with their GEM names (not the Debian package names) | |
40 | + | |
41 | +gem 'api-pagination', '~> 4.1.1' | |
42 | + | |
43 | +# asset pipeline | |
44 | +gem 'uglifier', '>= 1.0.3' | |
45 | +gem 'sass-rails' | |
27 | 46 | |
28 | 47 | group :production do |
29 | 48 | gem 'dalli', '~> 2.7.0' |
30 | 49 | end |
31 | 50 | |
32 | 51 | group :test do |
33 | - gem 'rspec', '~> 2.10.0' | |
34 | - gem 'rspec-rails', '~> 2.10.1' | |
52 | + gem 'rspec', '~> 2.14.0' | |
53 | + gem 'rspec-rails', '~> 2.14.1' | |
35 | 54 | gem 'mocha', '~> 1.1.0', :require => false |
36 | 55 | end |
37 | 56 | ... | ... |
... | ... | @@ -0,0 +1,281 @@ |
1 | +GIT | |
2 | + remote: https://github.com/aceunreal/grape_logging.git | |
3 | + revision: f1755ae4e1d897a65b20218d40681f59a9630f1b | |
4 | + ref: f1755ae | |
5 | + specs: | |
6 | + grape_logging (1.1.2) | |
7 | + grape | |
8 | + | |
9 | +GEM | |
10 | + remote: https://rubygems.org/ | |
11 | + specs: | |
12 | + RedCloth (4.2.9) | |
13 | + actionmailer (3.2.22) | |
14 | + actionpack (= 3.2.22) | |
15 | + mail (~> 2.5.4) | |
16 | + actionpack (3.2.22) | |
17 | + activemodel (= 3.2.22) | |
18 | + activesupport (= 3.2.22) | |
19 | + builder (~> 3.0.0) | |
20 | + erubis (~> 2.7.0) | |
21 | + journey (~> 1.0.4) | |
22 | + rack (~> 1.4.5) | |
23 | + rack-cache (~> 1.2) | |
24 | + rack-test (~> 0.6.1) | |
25 | + sprockets (~> 2.2.1) | |
26 | + activemodel (3.2.22) | |
27 | + activesupport (= 3.2.22) | |
28 | + builder (~> 3.0.0) | |
29 | + activerecord (3.2.22) | |
30 | + activemodel (= 3.2.22) | |
31 | + activesupport (= 3.2.22) | |
32 | + arel (~> 3.0.2) | |
33 | + tzinfo (~> 0.3.29) | |
34 | + activeresource (3.2.22) | |
35 | + activemodel (= 3.2.22) | |
36 | + activesupport (= 3.2.22) | |
37 | + activesupport (3.2.22) | |
38 | + i18n (~> 0.6, >= 0.6.4) | |
39 | + multi_json (~> 1.0) | |
40 | + acts-as-taggable-on (3.4.4) | |
41 | + activerecord (>= 3.2, < 5) | |
42 | + api-pagination (4.1.1) | |
43 | + arel (3.0.3) | |
44 | + axiom-types (0.1.1) | |
45 | + descendants_tracker (~> 0.0.4) | |
46 | + ice_nine (~> 0.11.0) | |
47 | + thread_safe (~> 0.3, >= 0.3.1) | |
48 | + builder (3.0.4) | |
49 | + capybara (2.1.0) | |
50 | + mime-types (>= 1.16) | |
51 | + nokogiri (>= 1.3.3) | |
52 | + rack (>= 1.0.0) | |
53 | + rack-test (>= 0.5.4) | |
54 | + xpath (~> 2.0) | |
55 | + childprocess (0.5.6) | |
56 | + ffi (~> 1.0, >= 1.0.11) | |
57 | + chronic (0.10.2) | |
58 | + coercible (1.0.0) | |
59 | + descendants_tracker (~> 0.0.1) | |
60 | + cucumber (1.0.6) | |
61 | + builder (>= 2.1.2) | |
62 | + diff-lcs (>= 1.1.2) | |
63 | + gherkin (~> 2.4.18) | |
64 | + json (>= 1.4.6) | |
65 | + term-ansicolor (>= 1.0.6) | |
66 | + cucumber-rails (1.0.6) | |
67 | + capybara (>= 1.1.1) | |
68 | + cucumber (>= 1.0.6) | |
69 | + nokogiri (>= 1.5.0) | |
70 | + daemons (1.1.9) | |
71 | + dalli (2.7.4) | |
72 | + database_cleaner (1.2.0) | |
73 | + descendants_tracker (0.0.4) | |
74 | + thread_safe (~> 0.3, >= 0.3.1) | |
75 | + diff-lcs (1.2.5) | |
76 | + eita-jrails (0.9.5) | |
77 | + actionpack (~> 3.2, >= 3.1.0) | |
78 | + activesupport (~> 3.2, >= 3.0.0) | |
79 | + equalizer (0.0.11) | |
80 | + erubis (2.7.0) | |
81 | + eventmachine (1.0.7) | |
82 | + exception_notification (4.0.1) | |
83 | + actionmailer (>= 3.0.4) | |
84 | + activesupport (>= 3.0.4) | |
85 | + execjs (2.5.2) | |
86 | + fast_gettext (0.6.12) | |
87 | + ffi (1.9.10) | |
88 | + gettext (2.2.1) | |
89 | + locale | |
90 | + gherkin (2.4.21) | |
91 | + json (>= 1.4.6) | |
92 | + git-version-bump (0.15.1) | |
93 | + grape (0.12.0) | |
94 | + activesupport | |
95 | + builder | |
96 | + hashie (>= 2.1.0) | |
97 | + multi_json (>= 1.3.2) | |
98 | + multi_xml (>= 0.5.2) | |
99 | + rack (>= 1.3.0) | |
100 | + rack-accept | |
101 | + rack-mount | |
102 | + virtus (>= 1.0.0) | |
103 | + grape-entity (0.4.5) | |
104 | + activesupport | |
105 | + multi_json (>= 1.3.2) | |
106 | + hashie (2.1.2) | |
107 | + hike (1.2.3) | |
108 | + i18n (0.7.0) | |
109 | + ice_nine (0.11.1) | |
110 | + journey (1.0.4) | |
111 | + json (1.8.3) | |
112 | + libv8 (3.16.14.11) | |
113 | + liquid (3.0.6) | |
114 | + locale (2.0.9) | |
115 | + magic (0.2.9) | |
116 | + ffi (>= 0.6.3) | |
117 | + mail (2.5.4) | |
118 | + mime-types (~> 1.16) | |
119 | + treetop (~> 1.4.8) | |
120 | + metaclass (0.0.4) | |
121 | + mime-types (1.25.1) | |
122 | + mini_portile (0.6.2) | |
123 | + minitest (3.2.0) | |
124 | + mocha (1.1.0) | |
125 | + metaclass (~> 0.0.1) | |
126 | + multi_json (1.11.2) | |
127 | + multi_xml (0.5.5) | |
128 | + nokogiri (1.6.6.2) | |
129 | + mini_portile (~> 0.6.0) | |
130 | + pg (0.13.2) | |
131 | + polyglot (0.3.5) | |
132 | + rack (1.4.7) | |
133 | + rack-accept (0.4.5) | |
134 | + rack (>= 0.4) | |
135 | + rack-cache (1.2) | |
136 | + rack (>= 0.4) | |
137 | + rack-contrib (1.3.0) | |
138 | + git-version-bump (~> 0.15) | |
139 | + rack (~> 1.4) | |
140 | + rack-cors (0.4.0) | |
141 | + rack-mount (0.8.3) | |
142 | + rack (>= 1.0.0) | |
143 | + rack-ssl (1.3.4) | |
144 | + rack | |
145 | + rack-test (0.6.3) | |
146 | + rack (>= 1.0) | |
147 | + rails (3.2.22) | |
148 | + actionmailer (= 3.2.22) | |
149 | + actionpack (= 3.2.22) | |
150 | + activerecord (= 3.2.22) | |
151 | + activeresource (= 3.2.22) | |
152 | + activesupport (= 3.2.22) | |
153 | + bundler (~> 1.0) | |
154 | + railties (= 3.2.22) | |
155 | + rails_autolink (1.1.6) | |
156 | + rails (> 3.1) | |
157 | + railties (3.2.22) | |
158 | + actionpack (= 3.2.22) | |
159 | + activesupport (= 3.2.22) | |
160 | + rack-ssl (~> 1.3.2) | |
161 | + rake (>= 0.8.7) | |
162 | + rdoc (~> 3.4) | |
163 | + thor (>= 0.14.6, < 2.0) | |
164 | + rake (10.4.2) | |
165 | + rdoc (3.12.2) | |
166 | + json (~> 1.4) | |
167 | + ref (2.0.0) | |
168 | + rest-client (1.6.9) | |
169 | + mime-types (~> 1.16) | |
170 | + rmagick (2.13.4) | |
171 | + rspec (2.14.1) | |
172 | + rspec-core (~> 2.14.0) | |
173 | + rspec-expectations (~> 2.14.0) | |
174 | + rspec-mocks (~> 2.14.0) | |
175 | + rspec-core (2.14.8) | |
176 | + rspec-expectations (2.14.5) | |
177 | + diff-lcs (>= 1.1.3, < 2.0) | |
178 | + rspec-mocks (2.14.6) | |
179 | + rspec-rails (2.14.2) | |
180 | + actionpack (>= 3.0) | |
181 | + activemodel (>= 3.0) | |
182 | + activesupport (>= 3.0) | |
183 | + railties (>= 3.0) | |
184 | + rspec-core (~> 2.14.0) | |
185 | + rspec-expectations (~> 2.14.0) | |
186 | + rspec-mocks (~> 2.14.0) | |
187 | + ruby-feedparser (0.9.3) | |
188 | + magic | |
189 | + rubyzip (1.1.7) | |
190 | + sass (3.4.15) | |
191 | + sass-rails (3.2.6) | |
192 | + railties (~> 3.2.0) | |
193 | + sass (>= 3.1.10) | |
194 | + tilt (~> 1.3) | |
195 | + selenium-webdriver (2.39.0) | |
196 | + childprocess (>= 0.2.5) | |
197 | + multi_json (~> 1.0) | |
198 | + rubyzip (~> 1.0) | |
199 | + websocket (~> 1.0.4) | |
200 | + sprockets (2.2.3) | |
201 | + hike (~> 1.2) | |
202 | + multi_json (~> 1.0) | |
203 | + rack (~> 1.0) | |
204 | + tilt (~> 1.1, != 1.3.0) | |
205 | + term-ansicolor (1.3.2) | |
206 | + tins (~> 1.0) | |
207 | + therubyracer (0.12.2) | |
208 | + libv8 (~> 3.16.14.0) | |
209 | + ref | |
210 | + thin (1.3.1) | |
211 | + daemons (>= 1.0.9) | |
212 | + eventmachine (>= 0.12.6) | |
213 | + rack (>= 1.0.0) | |
214 | + thor (0.19.1) | |
215 | + thread_safe (0.3.5) | |
216 | + tilt (1.4.1) | |
217 | + tins (1.5.4) | |
218 | + treetop (1.4.15) | |
219 | + polyglot | |
220 | + polyglot (>= 0.3.1) | |
221 | + tzinfo (0.3.44) | |
222 | + uglifier (2.7.1) | |
223 | + execjs (>= 0.3.0) | |
224 | + json (>= 1.8.0) | |
225 | + virtus (1.0.5) | |
226 | + axiom-types (~> 0.1) | |
227 | + coercible (~> 1.0) | |
228 | + descendants_tracker (~> 0.0, >= 0.0.3) | |
229 | + equalizer (~> 0.0, >= 0.0.9) | |
230 | + websocket (1.0.7) | |
231 | + whenever (0.9.4) | |
232 | + chronic (>= 0.6.3) | |
233 | + will_paginate (3.0.7) | |
234 | + xpath (2.0.0) | |
235 | + nokogiri (~> 1.3) | |
236 | + | |
237 | +PLATFORMS | |
238 | + ruby | |
239 | + | |
240 | +DEPENDENCIES | |
241 | + RedCloth (~> 4.2.9) | |
242 | + acts-as-taggable-on (~> 3.4.2) | |
243 | + api-pagination (~> 4.1.1) | |
244 | + capybara (~> 2.1.0) | |
245 | + cucumber (~> 1.0.6) | |
246 | + cucumber-rails (~> 1.0.6) | |
247 | + daemons (~> 1.1.5) | |
248 | + dalli (~> 2.7.0) | |
249 | + database_cleaner (~> 1.2.0) | |
250 | + eita-jrails (~> 0.9.5) | |
251 | + exception_notification (~> 4.0.1) | |
252 | + execjs | |
253 | + fast_gettext (~> 0.6.8) | |
254 | + gettext (~> 2.2.1) | |
255 | + grape (~> 0.12) | |
256 | + grape-entity | |
257 | + grape_logging! | |
258 | + liquid (~> 3.0.3) | |
259 | + locale (~> 2.0.5) | |
260 | + minitest (~> 3.2.0) | |
261 | + mocha (~> 1.1.0) | |
262 | + nokogiri (~> 1.6.0) | |
263 | + pg (~> 0.13.2) | |
264 | + rack-contrib | |
265 | + rack-cors | |
266 | + rails (~> 3.2.22) | |
267 | + rails_autolink (~> 1.1.5) | |
268 | + rake | |
269 | + rest-client (~> 1.6.7) | |
270 | + rmagick (~> 2.13.1) | |
271 | + rspec (~> 2.14.0) | |
272 | + rspec-rails (~> 2.14.1) | |
273 | + ruby-feedparser (~> 0.7) | |
274 | + rubyzip | |
275 | + sass-rails | |
276 | + selenium-webdriver (~> 2.39.0) | |
277 | + therubyracer | |
278 | + thin (~> 1.3.1) | |
279 | + uglifier (>= 1.0.3) | |
280 | + whenever | |
281 | + will_paginate (~> 3.0.3) | ... | ... |
INSTALL.chat.md
1 | -XMPP/Chat Setup | |
2 | -=============== | |
1 | +Automatic XMPP/Chat Setup | |
2 | +========================= | |
3 | + | |
4 | +Since Noosfero 1.2, the XMPP/Chat can be installed via `noosfero-chat` Debian | |
5 | +package. So you don't need to follow the manual instructions here if you | |
6 | +already have it installed on your system. | |
7 | + | |
8 | +But if you are going to install the `noosfero-chat` package on a system that | |
9 | +already has `noosfero` older 1.2 installed then you need to check if apache's | |
10 | +configuration file `/etc/apache2/sites-available/noosfero` has this line below: | |
11 | + | |
12 | + Include /usr/share/noosfero/util/chat/apache/xmpp.conf | |
13 | + | |
14 | +Manual XMPP/Chat Setup | |
15 | +====================== | |
3 | 16 | |
4 | 17 | The samples of config file to configure a XMPP/BOSH server with ejabberd, |
5 | 18 | postgresql and apache2 can be found at util/chat directory. |
... | ... | @@ -8,7 +21,7 @@ This setup supposes that you are using Noosfero installed via Debian package |
8 | 21 | in a production environment. |
9 | 22 | |
10 | 23 | Steps |
11 | -===== | |
24 | +----- | |
12 | 25 | |
13 | 26 | This is a step-by-step guide to get a XMPP service working, in a Debian system. |
14 | 27 | |
... | ... | @@ -144,15 +157,8 @@ You should see a page with a message like that: |
144 | 157 | |
145 | 158 | ## 9. Test chat session |
146 | 159 | |
147 | -Open Noosfero console and execute: | |
148 | - | |
149 | ->> environment = Environment.default | |
150 | ->> user = Person['guest'] | |
151 | ->> password = user.user.crypted_password | |
152 | ->> login = user.jid | |
153 | ->> RubyBOSH.initialize_session(login, password, "http://#{environment.default_hostname}/http-bind", :wait => 30, :hold => 1, :window => 5 | |
154 | - | |
155 | -If you have luck, should see something like that: | |
160 | +Run `./script/noosfero-test-chat-session`. If you have luck, should see | |
161 | +something like that: | |
156 | 162 | |
157 | 163 | Ruby-BOSH - SEND |
158 | 164 | <body window="5" rid="60265" xmlns="http://jabber.org/protocol/httpbind" xmlns:xmpp="urn:xmpp:xbosh" to="vagrant-debian-squeeze.vagrantup.com" wait="30" xmpp:version="1.0" hold="1"/> | ... | ... |
INSTALL.https.md
... | ... | @@ -11,8 +11,8 @@ as below: |
11 | 11 | |
12 | 12 | # mkdir /etc/noosfero/ssl |
13 | 13 | # cd /etc/noosfero/ssl |
14 | - # openssl genrsa 1024 > noosfero.key | |
15 | - # openssl req -new -x509 -nodes -sha1 -days $[10*365] -key noosfero.key > noosfero.cert | |
14 | + # openssl genrsa 2048 > noosfero.key | |
15 | + # openssl req -new -x509 -sha256 -nodes -days $[10*365] -key noosfero.key > noosfero.cert | |
16 | 16 | # cat noosfero.key noosfero.cert > noosfero.pem |
17 | 17 | |
18 | 18 | ## Web server configuration | ... | ... |
INSTALL.md
... | ... | @@ -74,7 +74,7 @@ downloading from git |
74 | 74 | |
75 | 75 | Here we are cloning the noosfero repository from git. Note: you will need to install git before. |
76 | 76 | |
77 | - $ git clone git://gitorious.org/noosfero/noosfero.git current | |
77 | + $ git clone https://gitlab.com/noosfero/noosfero.git current | |
78 | 78 | $ cd current |
79 | 79 | $ git checkout -b stable origin/stable |
80 | 80 | ... | ... |
Rakefile
... | ... | @@ -15,4 +15,21 @@ Noosfero::Application.load_tasks |
15 | 15 | Dir.glob(pattern).sort |
16 | 16 | end.flatten.each do |taskfile| |
17 | 17 | load taskfile |
18 | +end | |
19 | + | |
20 | +# plugins' tasks | |
21 | +plugins_tasks = Dir.glob("config/plugins/*/{tasks,lib/tasks,rails/tasks}/**/*.rake").sort + | |
22 | + Dir.glob("config/plugins/*/vendor/plugins/*/{tasks,lib/tasks,rails/tasks}/**/*.rake").sort | |
23 | +plugins_tasks.each{ |ext| load ext } | |
24 | + | |
25 | + | |
26 | +desc "Print out grape routes" | |
27 | +task :grape_routes => :environment do | |
28 | + #require 'api/api.rb' | |
29 | + Noosfero::API::API.routes.each do |route| | |
30 | + puts route | |
31 | + method = route.route_method | |
32 | + path = route.route_path | |
33 | + puts " #{method} #{path}" | |
34 | + end | |
18 | 35 | end | ... | ... |
app/controllers/admin/admin_panel_controller.rb
... | ... | @@ -71,22 +71,4 @@ 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, environment, scope, @q, {:per_page => 10, :page => params[:npage]})[:results] | |
91 | - end | |
92 | 74 | end | ... | ... |
app/controllers/admin/environment_design_controller.rb
1 | 1 | class EnvironmentDesignController < BoxOrganizerController |
2 | - | |
2 | + | |
3 | 3 | protect 'edit_environment_design', :environment |
4 | 4 | |
5 | + def filtered_available_blocks(blocks=nil) | |
6 | + filtered_available_blocks = [] | |
7 | + blocks.each { |block| filtered_available_blocks << block unless @environment.disabled_blocks.include?(block.name) } | |
8 | + filtered_available_blocks | |
9 | + end | |
10 | + | |
5 | 11 | def available_blocks |
6 | 12 | @available_blocks ||= [ ArticleBlock, LoginBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock, FeaturedProductsBlock, CategoriesBlock, RawHTMLBlock, TagsBlock ] |
7 | 13 | @available_blocks += plugins.dispatch(:extra_blocks, :type => Environment) |
8 | 14 | end |
9 | 15 | |
16 | + def index | |
17 | + available_blocks | |
18 | + end | |
19 | + | |
10 | 20 | end | ... | ... |
app/controllers/admin/environment_email_templates_controller.rb
0 → 100644
... | ... | @@ -0,0 +1,15 @@ |
1 | +class EnvironmentEmailTemplatesController < EmailTemplatesController | |
2 | + | |
3 | + protect 'manage_email_templates', :environment | |
4 | + | |
5 | + protected | |
6 | + | |
7 | + def owner | |
8 | + environment | |
9 | + end | |
10 | + | |
11 | + before_filter :only => :index do | |
12 | + @back_to = url_for(:controller => :admin_panel) | |
13 | + end | |
14 | + | |
15 | +end | ... | ... |
app/controllers/admin/features_controller.rb
1 | 1 | class FeaturesController < AdminController |
2 | + | |
2 | 3 | protect 'edit_environment_features', :environment |
3 | - | |
4 | + | |
4 | 5 | def index |
5 | 6 | @features = Environment.available_features.sort_by{|k,v|v} |
6 | 7 | end |
7 | 8 | |
9 | + def manage_blocks | |
10 | + @blocks = [ ArticleBlock, | |
11 | + TagsBlock, | |
12 | + RecentDocumentsBlock, | |
13 | + ProfileInfoBlock, | |
14 | + LinkListBlock, | |
15 | + MyNetworkBlock, | |
16 | + FeedReaderBlock, | |
17 | + ProfileImageBlock, | |
18 | + LocationBlock, | |
19 | + SlideshowBlock, | |
20 | + ProfileSearchBlock, | |
21 | + HighlightsBlock, | |
22 | + FriendsBlock, | |
23 | + FavoriteEnterprisesBlock, | |
24 | + CommunitiesBlock, | |
25 | + EnterprisesBlock, | |
26 | + MembersBlock, | |
27 | + DisabledEnterpriseMessageBlock, | |
28 | + ProductCategoriesBlock, | |
29 | + FeaturedProductsBlock, | |
30 | + FansBlock, | |
31 | + ProductsBlock ] | |
32 | + | |
33 | + @blocks += plugins.dispatch(:extra_blocks) | |
34 | + @blocks.sort_by! { |block| block.name } | |
35 | + end | |
36 | + | |
8 | 37 | post_only :update |
9 | 38 | def update |
10 | 39 | if @environment.update_attributes(params[:environment]) |
... | ... | @@ -15,6 +44,17 @@ class FeaturesController < AdminController |
15 | 44 | end |
16 | 45 | end |
17 | 46 | |
47 | + post_only :update_blocks | |
48 | + def update_blocks | |
49 | + params[:environment].delete(:available_blocks) | |
50 | + if @environment.update_attributes(params[:environment]) | |
51 | + session[:notice] = _('Blocks updated successfully.') | |
52 | + redirect_to :action => 'manage_blocks' | |
53 | + else | |
54 | + render :action => 'manage_blocks' | |
55 | + end | |
56 | + end | |
57 | + | |
18 | 58 | def manage_fields |
19 | 59 | @person_fields = Person.fields |
20 | 60 | @enterprise_fields = Enterprise.fields | ... | ... |
... | ... | @@ -0,0 +1,66 @@ |
1 | +class OrganizationsController < AdminController | |
2 | + | |
3 | + protect 'manage_environment_organizations', :environment | |
4 | + | |
5 | + def index | |
6 | + @filter = params[:filter] || 'any' | |
7 | + @title = _('Organization profiles') | |
8 | + @type = params[:type] || "any" | |
9 | + @types_filter = [[_('All'), 'any'], [_('Community'), 'Community'], [_('Enterprise'), 'Enterprise']] | |
10 | + @types_filter = @types_filter | @plugins.dispatch(:organization_types_filter_options) | |
11 | + | |
12 | + scope = @plugins.dispatch_first(:filter_manage_organization_scope, @type) | |
13 | + if scope.blank? | |
14 | + scope = environment.organizations | |
15 | + scope = scope.where(:type => @type) if @type != 'any' | |
16 | + end | |
17 | + | |
18 | + if @filter == 'enabled' | |
19 | + scope = scope.visible | |
20 | + elsif @filter == 'disabled' | |
21 | + scope = scope.disabled | |
22 | + end | |
23 | + | |
24 | + scope = scope.order('name ASC') | |
25 | + | |
26 | + @q = params[:q] | |
27 | + @collection = find_by_contents(:organizations, environment, scope, @q, {:per_page => per_page, :page => params[:npage]})[:results] | |
28 | + end | |
29 | + | |
30 | + def activate | |
31 | + organization = environment.organizations.find(params[:id]) | |
32 | + if organization.enable | |
33 | + render :text => (_('%s enabled') % organization.name).to_json | |
34 | + else | |
35 | + render :text => (_('%s could not be enabled') % organization.name).to_json | |
36 | + end | |
37 | + end | |
38 | + | |
39 | + def deactivate | |
40 | + organization = environment.organizations.find(params[:id]) | |
41 | + if organization.disable | |
42 | + render :text => (_('%s disabled') % organization.name).to_json | |
43 | + else | |
44 | + render :text => (_('%s could not be disable') % organization.name).to_json | |
45 | + end | |
46 | + end | |
47 | + | |
48 | + def destroy | |
49 | + if request.post? | |
50 | + organization = environment.organizations.find(params[:id]) | |
51 | + if organization && organization.destroy | |
52 | + render :text => (_('%s removed') % organization.name).to_json | |
53 | + else | |
54 | + render :text => (_('%s could not be removed') % organization.name).to_json | |
55 | + end | |
56 | + else | |
57 | + render :nothing => true | |
58 | + end | |
59 | + end | |
60 | + | |
61 | + private | |
62 | + | |
63 | + def per_page | |
64 | + 10 | |
65 | + end | |
66 | +end | ... | ... |
app/controllers/admin/role_controller.rb
app/controllers/application_controller.rb
... | ... | @@ -7,8 +7,17 @@ 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 | + | |
11 | + before_filter :login_from_cookie | |
10 | 12 | before_filter :login_required, :if => :private_environment? |
13 | + | |
11 | 14 | before_filter :verify_members_whitelist, :if => [:private_environment?, :user] |
15 | + before_filter :log_user | |
16 | + | |
17 | + def log_user | |
18 | + Rails.logger.info "Logged in: #{user.identifier}" if user | |
19 | + end | |
20 | + before_filter :redirect_to_current_user | |
12 | 21 | |
13 | 22 | def verify_members_whitelist |
14 | 23 | render_access_denied unless user.is_admin? || environment.in_whitelist?(user) |
... | ... | @@ -71,8 +80,8 @@ class ApplicationController < ActionController::Base |
71 | 80 | FastGettext.available_locales = environment.available_locales |
72 | 81 | FastGettext.default_locale = environment.default_locale |
73 | 82 | FastGettext.locale = (params[:lang] || session[:lang] || environment.default_locale || request.env['HTTP_ACCEPT_LANGUAGE'] || 'en') |
74 | - I18n.locale = FastGettext.locale | |
75 | - I18n.default_locale = FastGettext.default_locale | |
83 | + I18n.locale = FastGettext.locale.to_s.gsub '_', '-' | |
84 | + I18n.default_locale = FastGettext.default_locale.to_s.gsub '_', '-' | |
76 | 85 | if params[:lang] |
77 | 86 | session[:lang] = params[:lang] |
78 | 87 | end |
... | ... | @@ -192,4 +201,15 @@ class ApplicationController < ActionController::Base |
192 | 201 | def private_environment? |
193 | 202 | @environment.enabled?(:restrict_to_members) |
194 | 203 | end |
204 | + | |
205 | + def redirect_to_current_user | |
206 | + if params[:profile] == '~' | |
207 | + if logged_in? | |
208 | + redirect_to params.merge(:profile => user.identifier) | |
209 | + else | |
210 | + render_not_found | |
211 | + end | |
212 | + end | |
213 | + end | |
214 | + | |
195 | 215 | end | ... | ... |
app/controllers/box_organizer_controller.rb
... | ... | @@ -3,12 +3,11 @@ class BoxOrganizerController < ApplicationController |
3 | 3 | before_filter :login_required |
4 | 4 | |
5 | 5 | def index |
6 | + @available_blocks = available_blocks.uniq.sort_by(&:pretty_name) | |
6 | 7 | end |
7 | 8 | |
8 | 9 | def move_block |
9 | - @block = boxes_holder.blocks.find(params[:id].gsub(/^block-/, '')) | |
10 | - | |
11 | - @source_box = @block.box | |
10 | + @block = params[:id] ? boxes_holder.blocks.find(params[:id].gsub(/^block-/, '')) : nil | |
12 | 11 | |
13 | 12 | target_position = nil |
14 | 13 | |
... | ... | @@ -20,9 +19,12 @@ class BoxOrganizerController < ApplicationController |
20 | 19 | else |
21 | 20 | (params[:target] =~ /end-of-box-([0-9]+)/) |
22 | 21 | |
23 | - @target_box = boxes_holder.boxes.find($1) | |
22 | + @target_box = boxes_holder.boxes.find_by_id($1) | |
24 | 23 | end |
25 | 24 | |
25 | + @block = new_block(params[:type], @target_box) if @block.nil? | |
26 | + @source_box = @block.box | |
27 | + | |
26 | 28 | if (@source_box != @target_box) |
27 | 29 | @block.remove_from_list |
28 | 30 | @block.box = @target_box |
... | ... | @@ -58,23 +60,6 @@ class BoxOrganizerController < ApplicationController |
58 | 60 | redirect_to :action => 'index' |
59 | 61 | end |
60 | 62 | |
61 | - def add_block | |
62 | - type = params[:type] | |
63 | - if ! type.blank? | |
64 | - if available_blocks.map(&:name).include?(type) | |
65 | - boxes_holder.boxes.find(params[:box_id]).blocks << type.constantize.new | |
66 | - redirect_to :action => 'index' | |
67 | - else | |
68 | - raise ArgumentError.new("Type %s is not allowed. Go away." % type) | |
69 | - end | |
70 | - else | |
71 | - @center_block_types = (Box.acceptable_center_blocks & available_blocks) + plugins.dispatch(:extra_blocks, :type => boxes_holder.class, :position => 1) | |
72 | - @side_block_types = (Box.acceptable_side_blocks & available_blocks) + plugins.dispatch(:extra_blocks, :type => boxes_holder.class, :position => [2,3]) | |
73 | - @boxes = boxes_holder.boxes.with_position | |
74 | - render :action => 'add_block', :layout => false | |
75 | - end | |
76 | - end | |
77 | - | |
78 | 63 | def edit |
79 | 64 | @block = boxes_holder.blocks.find(params[:id]) |
80 | 65 | render :action => 'edit', :layout => false |
... | ... | @@ -98,8 +83,12 @@ class BoxOrganizerController < ApplicationController |
98 | 83 | |
99 | 84 | def save |
100 | 85 | @block = boxes_holder.blocks.find(params[:id]) |
101 | - @block.update_attributes(params[:block]) | |
102 | - redirect_to :action => 'index' | |
86 | + if @block.kind_of?(RawHTMLBlock) && !user.is_admin?(environment) | |
87 | + render_access_denied | |
88 | + else | |
89 | + @block.update_attributes(params[:block]) | |
90 | + redirect_to :action => 'index' | |
91 | + end | |
103 | 92 | end |
104 | 93 | |
105 | 94 | def boxes_editor? |
... | ... | @@ -121,6 +110,27 @@ class BoxOrganizerController < ApplicationController |
121 | 110 | redirect_to :action => 'index' |
122 | 111 | end |
123 | 112 | |
113 | + def show_block_type_info | |
114 | + type = params[:type] | |
115 | + if type.blank? || !available_blocks.map(&:name).include?(type) | |
116 | + raise ArgumentError.new("Type %s is not allowed. Go away." % type) | |
117 | + end | |
118 | + @block = type.constantize.new | |
119 | + @block.box = Box.new(:owner => boxes_holder) | |
120 | + render :action => 'show_block_type_info', :layout => false | |
121 | + end | |
122 | + | |
124 | 123 | protected :boxes_editor? |
125 | 124 | |
125 | + protected | |
126 | + | |
127 | + def new_block(type, box) | |
128 | + if !available_blocks.map(&:name).include?(type) | |
129 | + raise ArgumentError.new("Type %s is not allowed. Go away." % type) | |
130 | + end | |
131 | + block = type.constantize.new | |
132 | + box.blocks << block | |
133 | + block | |
134 | + end | |
135 | + | |
126 | 136 | end | ... | ... |
... | ... | @@ -0,0 +1,62 @@ |
1 | +class EmailTemplatesController < ApplicationController | |
2 | + | |
3 | + def index | |
4 | + @email_templates = owner.email_templates | |
5 | + end | |
6 | + | |
7 | + def show | |
8 | + @email_template = owner.email_templates.find(params[:id]) | |
9 | + | |
10 | + respond_to do |format| | |
11 | + format.html # show.html.erb | |
12 | + format.json { render json: @email_template } | |
13 | + end | |
14 | + end | |
15 | + | |
16 | + def show_parsed | |
17 | + @email_template = owner.email_templates.find(params[:id]) | |
18 | + template_params = {:profile => owner, :environment => environment} | |
19 | + render json: {:parsed_body => @email_template.parsed_body(template_params), :parsed_subject => @email_template.parsed_subject(template_params)} | |
20 | + end | |
21 | + | |
22 | + def new | |
23 | + @email_template = owner.email_templates.build(:owner => owner) | |
24 | + end | |
25 | + | |
26 | + def edit | |
27 | + @email_template = owner.email_templates.find(params[:id]) | |
28 | + end | |
29 | + | |
30 | + def create | |
31 | + @email_template = owner.email_templates.build(params[:email_template]) | |
32 | + @email_template.owner = owner | |
33 | + | |
34 | + if @email_template.save | |
35 | + session[:notice] = _('Email template was successfully created.') | |
36 | + redirect_to url_for(:action => :index) | |
37 | + else | |
38 | + render action: "new" | |
39 | + end | |
40 | + end | |
41 | + | |
42 | + def update | |
43 | + @email_template = owner.email_templates.find(params[:id]) | |
44 | + | |
45 | + if @email_template.update_attributes(params[:email_template]) | |
46 | + session[:notice] = _('Email template was successfully updated.') | |
47 | + redirect_to url_for(:action => :index) | |
48 | + else | |
49 | + render action: "edit" | |
50 | + end | |
51 | + end | |
52 | + | |
53 | + def destroy | |
54 | + @email_template = owner.email_templates.find(params[:id]) | |
55 | + @email_template.destroy | |
56 | + | |
57 | + respond_to do |format| | |
58 | + format.html { redirect_to url_for(:action => :index)} | |
59 | + format.json { head :no_content } | |
60 | + end | |
61 | + end | |
62 | +end | ... | ... |
app/controllers/my_profile/cms_controller.rb
... | ... | @@ -6,7 +6,7 @@ class CmsController < MyProfileController |
6 | 6 | |
7 | 7 | def search_tags |
8 | 8 | arg = params[:term].downcase |
9 | - result = ActsAsTaggableOn::Tag.find(:all, :conditions => ['LOWER(name) LIKE ?', "%#{arg}%"]) | |
9 | + result = ActsAsTaggableOn::Tag.where('name ILIKE ?', "%#{arg}%").limit(10) | |
10 | 10 | render :text => prepare_to_token_input_by_label(result).to_json, :content_type => 'application/json' |
11 | 11 | end |
12 | 12 | |
... | ... | @@ -27,20 +27,13 @@ class CmsController < MyProfileController |
27 | 27 | |
28 | 28 | helper_method :file_types |
29 | 29 | |
30 | - protect_if :only => :upload_files do |c, user, profile| | |
31 | - article_id = c.params[:parent_id] | |
32 | - (!article_id.blank? && profile.articles.find(article_id).allow_create?(user)) || | |
33 | - (user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile))) | |
34 | - end | |
35 | - | |
36 | - protect_if :except => [:suggest_an_article, :set_home_page, :edit, :destroy, :publish, :publish_on_portal_community, :publish_on_communities, :search_communities_to_publish, :upload_files, :new] do |c, user, profile| | |
30 | + protect_if :except => [:suggest_an_article, :set_home_page, :edit, :destroy, :publish, :upload_files, :new] do |c, user, profile| | |
37 | 31 | user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile)) |
38 | 32 | end |
39 | 33 | |
40 | - protect_if :only => :new do |c, user, profile| | |
41 | - article = profile.articles.find_by_id(c.params[:parent_id]) | |
42 | - (!article.nil? && (article.allow_create?(user) || article.parent.allow_create?(user))) || | |
43 | - (user && (user.has_permission?('post_content', profile) || user.has_permission?('publish_content', profile))) | |
34 | + protect_if :only => [:new, :upload_files] do |c, user, profile| | |
35 | + parent = profile.articles.find_by_id(c.params[:parent_id]) | |
36 | + user && user.can_post_content?(profile, parent) | |
44 | 37 | end |
45 | 38 | |
46 | 39 | protect_if :only => :destroy do |c, user, profile| |
... | ... | @@ -101,6 +94,11 @@ class CmsController < MyProfileController |
101 | 94 | record_coming |
102 | 95 | if request.post? |
103 | 96 | @article.image = nil if params[:remove_image] == 'true' |
97 | + if @article.image.present? && params[:article][:image_builder] && | |
98 | + params[:article][:image_builder][:label] | |
99 | + @article.image.label = params[:article][:image_builder][:label] | |
100 | + @article.image.save! | |
101 | + end | |
104 | 102 | @article.last_changed_by = user |
105 | 103 | if @article.update_attributes(params[:article]) |
106 | 104 | if !continue |
... | ... | @@ -112,6 +110,11 @@ class CmsController < MyProfileController |
112 | 110 | end |
113 | 111 | end |
114 | 112 | end |
113 | + | |
114 | + unless @article.kind_of?(RssFeed) | |
115 | + @escaped_body = CGI::escapeHTML(@article.body || '') | |
116 | + @escaped_abstract = CGI::escapeHTML(@article.abstract || '') | |
117 | + end | |
115 | 118 | end |
116 | 119 | |
117 | 120 | def new |
... | ... | @@ -143,7 +146,14 @@ class CmsController < MyProfileController |
143 | 146 | klass = @type.constantize |
144 | 147 | article_data = environment.enabled?('articles_dont_accept_comments_by_default') ? { :accept_comments => false } : {} |
145 | 148 | article_data.merge!(params[:article]) if params[:article] |
146 | - @article = klass.new(article_data) | |
149 | + article_data.merge!(:profile => profile) if profile | |
150 | + | |
151 | + @article = if params[:clone] | |
152 | + current_article = profile.articles.find(params[:id]) | |
153 | + current_article.copy_without_save | |
154 | + else | |
155 | + klass.new(article_data) | |
156 | + end | |
147 | 157 | |
148 | 158 | parent = check_parent(params[:parent_id]) |
149 | 159 | if parent |
... | ... | @@ -220,7 +230,7 @@ class CmsController < MyProfileController |
220 | 230 | if @errors.any? |
221 | 231 | render :action => 'upload_files', :parent_id => @parent_id |
222 | 232 | else |
223 | - session[:notice] = _('File(s) successfully uploaded') | |
233 | + session[:notice] = _('File(s) successfully uploaded') | |
224 | 234 | if @back_to |
225 | 235 | redirect_to @back_to |
226 | 236 | elsif @parent |
... | ... | @@ -357,7 +367,8 @@ class CmsController < MyProfileController |
357 | 367 | @task.ip_address = request.remote_ip |
358 | 368 | @task.user_agent = request.user_agent |
359 | 369 | @task.referrer = request.referrer |
360 | - if verify_recaptcha(:model => @task, :message => _('Please type the words correctly')) && @task.save | |
370 | + @task.requestor = current_person if logged_in? | |
371 | + if (logged_in? || verify_recaptcha(:model => @task, :message => _('Please type the words correctly'))) && @task.save | |
361 | 372 | session[:notice] = _('Thanks for your suggestion. The community administrators were notified.') |
362 | 373 | redirect_to @back_to |
363 | 374 | end |
... | ... | @@ -453,7 +464,8 @@ class CmsController < MyProfileController |
453 | 464 | end |
454 | 465 | |
455 | 466 | def refuse_blocks |
456 | - if ['TinyMceArticle', 'TextileArticle', 'Event', 'EnterpriseHomepage'].include?(@type) | |
467 | + article_types = ['TinyMceArticle', 'TextileArticle', 'Event', 'EnterpriseHomepage'] + @plugins.dispatch(:content_types).map {|type| type.name} | |
468 | + if article_types.include?(@type) | |
457 | 469 | @no_design_blocks = true |
458 | 470 | end |
459 | 471 | end | ... | ... |
app/controllers/my_profile/enterprise_validation_controller.rb
1 | 1 | class EnterpriseValidationController < MyProfileController |
2 | 2 | |
3 | 3 | protect 'validate_enterprise', :profile |
4 | - | |
4 | + | |
5 | 5 | def index |
6 | 6 | @pending_validations = profile.pending_validations |
7 | 7 | end |
... | ... | @@ -27,7 +27,7 @@ class EnterpriseValidationController < MyProfileController |
27 | 27 | post_only :reject |
28 | 28 | def reject |
29 | 29 | @pending = profile.find_pending_validation(params[:id]) |
30 | - if @pending | |
30 | + if @pending | |
31 | 31 | @pending.reject_explanation = params[:reject_explanation] |
32 | 32 | begin |
33 | 33 | @pending.reject | ... | ... |
app/controllers/my_profile/favorite_enterprises_controller.rb
1 | 1 | class FavoriteEnterprisesController < MyProfileController |
2 | - | |
3 | -# protect 'manage_favorite_enteprises', :profile | |
2 | + | |
3 | +# protect 'manage_favorite_enterprises', :profile | |
4 | 4 | |
5 | 5 | requires_profile_class Person |
6 | - | |
6 | + | |
7 | 7 | def index |
8 | 8 | @favorite_enterprises = profile.favorite_enterprises |
9 | 9 | end |
... | ... | @@ -12,7 +12,7 @@ class FavoriteEnterprisesController < MyProfileController |
12 | 12 | @favorite_enterprise = Enterprise.find(params[:id]) |
13 | 13 | if request.post? && params[:confirmation] |
14 | 14 | profile.favorite_enterprises << @favorite_enterprise |
15 | - redirect_to :action => 'index' | |
15 | + redirect_to :action => 'index' | |
16 | 16 | end |
17 | 17 | end |
18 | 18 | ... | ... |
app/controllers/my_profile/friends_controller.rb
1 | 1 | class FriendsController < MyProfileController |
2 | - | |
2 | + | |
3 | 3 | protect 'manage_friends', :profile |
4 | - | |
4 | + | |
5 | 5 | def index |
6 | - @suggestions = profile.profile_suggestions.of_person.enabled.includes(:suggestion).limit(per_page) | |
6 | + @suggestions = profile.suggested_profiles.of_person.enabled.includes(:suggestion).limit(per_page) | |
7 | 7 | if is_cache_expired?(profile.manage_friends_cache_key(params)) |
8 | 8 | @friends = profile.friends.paginate(:per_page => per_page, :page => params[:npage]) |
9 | 9 | end |
... | ... | @@ -18,7 +18,7 @@ class FriendsController < MyProfileController |
18 | 18 | end |
19 | 19 | |
20 | 20 | def suggest |
21 | - @suggestions = profile.profile_suggestions.of_person.enabled.includes(:suggestion).limit(per_page) | |
21 | + @suggestions = profile.suggested_profiles.of_person.enabled.includes(:suggestion).limit(per_page) | |
22 | 22 | end |
23 | 23 | |
24 | 24 | def remove_suggestion |
... | ... | @@ -26,13 +26,13 @@ class FriendsController < MyProfileController |
26 | 26 | redirect_to :action => 'suggest' unless @person |
27 | 27 | if @person && request.post? |
28 | 28 | profile.remove_suggestion(@person) |
29 | - @suggestions = profile.profile_suggestions.of_person.enabled.includes(:suggestion).limit(per_page) | |
29 | + @suggestions = profile.suggested_profiles.of_person.enabled.includes(:suggestion).limit(per_page) | |
30 | 30 | render :partial => 'shared/profile_suggestions_list', :locals => { :suggestions => @suggestions, :collection => :friends_suggestions, :per_page => params[:per_page] || per_page } |
31 | 31 | end |
32 | 32 | end |
33 | 33 | |
34 | 34 | def connections |
35 | - @suggestion = profile.profile_suggestions.of_person.enabled.find_by_suggestion_id(params[:id]) | |
35 | + @suggestion = profile.suggested_profiles.of_person.enabled.find_by_suggestion_id(params[:id]) | |
36 | 36 | if @suggestion |
37 | 37 | @tags = @suggestion.tag_connections |
38 | 38 | @profiles = @suggestion.profile_connections | ... | ... |
app/controllers/my_profile/manage_products_controller.rb
... | ... | @@ -35,7 +35,7 @@ class ManageProductsController < ApplicationController |
35 | 35 | end |
36 | 36 | |
37 | 37 | def categories_for_selection |
38 | - @category = Category.find(params[:category_id]) if params[:category_id] | |
38 | + @category = environment.categories.find_by_id params[:category_id] | |
39 | 39 | @object_name = params[:object_name] |
40 | 40 | if @category |
41 | 41 | @categories = @category.children |
... | ... | @@ -95,6 +95,20 @@ class ManageProductsController < ApplicationController |
95 | 95 | end |
96 | 96 | end |
97 | 97 | |
98 | + def show_category_tree | |
99 | + @category = environment.categories.find params[:category_id] | |
100 | + render :partial => 'selected_category_tree' | |
101 | + end | |
102 | + | |
103 | + def search_categories | |
104 | + @term = params[:term].downcase | |
105 | + conditions = ['LOWER(name) LIKE ? OR LOWER(name) LIKE ?', "#{@term}%", "% #{@term}%"] | |
106 | + @categories = ProductCategory.all :conditions => conditions, :limit => 10 | |
107 | + render :json => (@categories.map do |category| | |
108 | + {:label => category.name, :value => category.id} | |
109 | + end) | |
110 | + end | |
111 | + | |
98 | 112 | def add_input |
99 | 113 | @product = @profile.products.find(params[:id]) |
100 | 114 | @input = @product.inputs.build |
... | ... | @@ -192,7 +206,8 @@ class ManageProductsController < ApplicationController |
192 | 206 | end |
193 | 207 | |
194 | 208 | def certifiers_for_selection |
195 | - @qualifier = Qualifier.exists?(params[:id]) ? Qualifier.find(params[:id]) : nil | |
209 | + # updated to use hash as argument to exists? to avoid sql injection vunerabillity (http://brakemanscanner.org/docs/warning_types/sql_injection/) | |
210 | + @qualifier = Qualifier.exists?(:id => params[:id]) ? Qualifier.find(params[:id]) : nil | |
196 | 211 | render :update do |page| |
197 | 212 | page.replace_html params[:certifier_area], :partial => 'certifiers_for_selection' |
198 | 213 | end | ... | ... |
app/controllers/my_profile/maps_controller.rb
... | ... | @@ -16,6 +16,7 @@ class MapsController < MyProfileController |
16 | 16 | |
17 | 17 | Profile.transaction do |
18 | 18 | if profile.update_attributes!(params[:profile_data]) |
19 | + BlockSweeper.expire_blocks profile.blocks.select{ |b| b.class == LocationBlock } | |
19 | 20 | session[:notice] = _('Address was updated successfully!') |
20 | 21 | redirect_to :action => 'edit_location' |
21 | 22 | end | ... | ... |
app/controllers/my_profile/memberships_controller.rb
... | ... | @@ -40,7 +40,7 @@ class MembershipsController < MyProfileController |
40 | 40 | end |
41 | 41 | |
42 | 42 | def suggest |
43 | - @suggestions = profile.profile_suggestions.of_community.enabled.includes(:suggestion).limit(per_page) | |
43 | + @suggestions = profile.suggested_profiles.of_community.enabled.includes(:suggestion).limit(per_page) | |
44 | 44 | end |
45 | 45 | |
46 | 46 | def remove_suggestion |
... | ... | @@ -49,13 +49,13 @@ class MembershipsController < MyProfileController |
49 | 49 | redirect_to :action => 'suggest' unless @community |
50 | 50 | if @community && request.post? |
51 | 51 | profile.remove_suggestion(@community) |
52 | - @suggestions = profile.profile_suggestions.of_community.enabled.includes(:suggestion).limit(custom_per_page) | |
52 | + @suggestions = profile.suggested_profiles.of_community.enabled.includes(:suggestion).limit(custom_per_page) | |
53 | 53 | render :partial => 'shared/profile_suggestions_list', :locals => { :suggestions => @suggestions, :collection => :communities_suggestions, :per_page => custom_per_page} |
54 | 54 | end |
55 | 55 | end |
56 | 56 | |
57 | 57 | def connections |
58 | - @suggestion = profile.profile_suggestions.of_community.enabled.find_by_suggestion_id(params[:id]) | |
58 | + @suggestion = profile.suggested_profiles.of_community.enabled.find_by_suggestion_id(params[:id]) | |
59 | 59 | if @suggestion |
60 | 60 | @tags = @suggestion.tag_connections |
61 | 61 | @profiles = @suggestion.profile_connections | ... | ... |
app/controllers/my_profile/profile_design_controller.rb
... | ... | @@ -4,11 +4,20 @@ class ProfileDesignController < BoxOrganizerController |
4 | 4 | |
5 | 5 | protect 'edit_profile_design', :profile |
6 | 6 | |
7 | - before_filter :protect_fixed_block, :only => [:save, :move_block] | |
7 | + before_filter :protect_uneditable_block, :only => [:save] | |
8 | + before_filter :protect_fixed_block, :only => [:move_block] | |
9 | + | |
10 | + def protect_uneditable_block | |
11 | + block = boxes_holder.blocks.find(params[:id].gsub(/^block-/, '')) | |
12 | + if !current_person.is_admin? && !block.editable? | |
13 | + render_access_denied | |
14 | + end | |
15 | + end | |
8 | 16 | |
9 | 17 | def protect_fixed_block |
18 | + return if params[:id].blank? | |
10 | 19 | block = boxes_holder.blocks.find(params[:id].gsub(/^block-/, '')) |
11 | - if block.fixed && !current_person.is_admin? | |
20 | + if block.present? && !current_person.is_admin? && !block.movable? | |
12 | 21 | render_access_denied |
13 | 22 | end |
14 | 23 | end | ... | ... |
app/controllers/my_profile/profile_editor_controller.rb
... | ... | @@ -5,6 +5,7 @@ class ProfileEditorController < MyProfileController |
5 | 5 | |
6 | 6 | before_filter :access_welcome_page, :only => [:welcome_page] |
7 | 7 | before_filter :back_to |
8 | + before_filter :forbid_destroy_profile, :only => [:destroy_profile] | |
8 | 9 | helper_method :has_welcome_page |
9 | 10 | |
10 | 11 | def index |
... | ... | @@ -18,7 +19,10 @@ class ProfileEditorController < MyProfileController |
18 | 19 | @profile_data = profile |
19 | 20 | @possible_domains = profile.possible_domains |
20 | 21 | if request.post? |
21 | - params[:profile_data][:fields_privacy] ||= {} if profile.person? && params[:profile_data].is_a?(Hash) | |
22 | + if profile.person? && params[:profile_data].is_a?(Hash) | |
23 | + params[:profile_data][:fields_privacy] ||= {} | |
24 | + params[:profile_data][:custom_fields] ||= {} | |
25 | + end | |
22 | 26 | Profile.transaction do |
23 | 27 | Image.transaction do |
24 | 28 | begin |
... | ... | @@ -109,7 +113,7 @@ class ProfileEditorController < MyProfileController |
109 | 113 | profile = environment.profiles.find(params[:id]) |
110 | 114 | if profile.disable |
111 | 115 | profile.save |
112 | - session[:notice] = _("The profile '#{profile.name}' was deactivated.") | |
116 | + session[:notice] = _("The profile '%s' was deactivated.") % profile.name | |
113 | 117 | else |
114 | 118 | session[:notice] = _('Could not deactivate profile.') |
115 | 119 | end |
... | ... | @@ -123,7 +127,7 @@ class ProfileEditorController < MyProfileController |
123 | 127 | profile = environment.profiles.find(params[:id]) |
124 | 128 | |
125 | 129 | if profile.enable |
126 | - session[:notice] = _("The profile '#{profile.name}' was activated.") | |
130 | + session[:notice] = _("The profile '%s' was activated.") % profile.name | |
127 | 131 | else |
128 | 132 | session[:notice] = _('Could not activate the profile.') |
129 | 133 | end |
... | ... | @@ -155,4 +159,10 @@ class ProfileEditorController < MyProfileController |
155 | 159 | end |
156 | 160 | end |
157 | 161 | |
162 | + def forbid_destroy_profile | |
163 | + if environment.enabled?('forbid_destroy_profile') && !current_person.is_admin?(environment) | |
164 | + session[:notice] = _('You can not destroy the profile.') | |
165 | + redirect_to_previous_location | |
166 | + end | |
167 | + end | |
158 | 168 | end | ... | ... |
app/controllers/my_profile/profile_email_templates_controller.rb
0 → 100644
... | ... | @@ -0,0 +1,16 @@ |
1 | +class ProfileEmailTemplatesController < EmailTemplatesController | |
2 | + | |
3 | + needs_profile | |
4 | + protect 'manage_email_templates', :profile | |
5 | + | |
6 | + protected | |
7 | + | |
8 | + def owner | |
9 | + profile | |
10 | + end | |
11 | + | |
12 | + before_filter :only => :index do | |
13 | + @back_to = url_for(:controller => :profile_editor) | |
14 | + end | |
15 | + | |
16 | +end | ... | ... |
app/controllers/my_profile/profile_members_controller.rb
... | ... | @@ -58,6 +58,7 @@ class ProfileMembersController < MyProfileController |
58 | 58 | |
59 | 59 | def change_role |
60 | 60 | @roles = Profile::Roles.organization_member_roles(environment.id) |
61 | + @custom_roles = profile.custom_roles | |
61 | 62 | begin |
62 | 63 | @member = profile.members.find(params[:id]) |
63 | 64 | rescue ActiveRecord::RecordNotFound | ... | ... |
... | ... | @@ -0,0 +1,116 @@ |
1 | +class ProfileRolesController < MyProfileController | |
2 | + | |
3 | + protect 'manage_custom_roles', :profile | |
4 | + | |
5 | + def index | |
6 | + @roles = profile.custom_roles | |
7 | + end | |
8 | + | |
9 | + def new | |
10 | + @role = Role.new | |
11 | + end | |
12 | + | |
13 | + def create | |
14 | + @role = Role.new({:name => params[:role][:name], :permissions => params[:role][:permissions], :environment => environment }, :without_protection => true) | |
15 | + if @role.save | |
16 | + profile.custom_roles << @role | |
17 | + redirect_to :action => 'show', :id => @role | |
18 | + else | |
19 | + session[:notice] = _('Failed to create role') | |
20 | + render :action => 'new' | |
21 | + end | |
22 | + end | |
23 | + | |
24 | + def show | |
25 | + @role = environment.roles.find(params[:id]) | |
26 | + end | |
27 | + | |
28 | + def edit | |
29 | + @role = environment.roles.find(params[:id]) | |
30 | + end | |
31 | + | |
32 | + def assign_role_by_members | |
33 | + return redirect_to "/" if params[:q].nil? or !request.xhr? | |
34 | + arg = params[:q].downcase | |
35 | + result = find_by_contents(:people, environment, profile.members, params[:q])[:results] | |
36 | + render :text => prepare_to_token_input(result).to_json | |
37 | + end | |
38 | + | |
39 | + def destroy | |
40 | + @role = environment.roles.find(params[:id]) | |
41 | + @members = profile.members_by_role(@role) | |
42 | + @roles_list = all_roles(environment, profile) | |
43 | + @roles_list.delete(@role) | |
44 | + end | |
45 | + | |
46 | + def remove | |
47 | + @role = environment.roles.find(params[:id]) | |
48 | + @members = profile.members_by_role(@role) | |
49 | + member_roles = params[:roles] ? environment.roles.find(params[:roles].select{|r|!r.to_i.zero?}) : [] | |
50 | + append_roles(@members, member_roles, profile) | |
51 | + if @role.destroy | |
52 | + session[:notice] = _('Role successfuly removed!') | |
53 | + else | |
54 | + session[:notice] = _('Failed to remove role!') | |
55 | + end | |
56 | + redirect_to :action => 'index' | |
57 | + end | |
58 | + | |
59 | + def update | |
60 | + @role = environment.roles.find(params[:id]) | |
61 | + if @role.update_attributes(params[:role]) | |
62 | + redirect_to :action => 'show', :id => @role | |
63 | + else | |
64 | + session[:notice] = _('Failed to edit role') | |
65 | + render :action => 'edit' | |
66 | + end | |
67 | + end | |
68 | + | |
69 | + def assign | |
70 | + @role = environment.roles.find(params[:id]) | |
71 | + @roles_list = all_roles(environment, profile) | |
72 | + @roles_list.delete(@role) | |
73 | + end | |
74 | + | |
75 | + def define | |
76 | + @role = environment.roles.find(params[:id]) | |
77 | + selected_role = params[:selected_role] ? environment.roles.find(params[:selected_role].to_i) : nil | |
78 | + if params[:assign_role_by].eql? "members" | |
79 | + members_list = params[:person_id].split(',').collect {|id| environment.profiles.find(id.to_i)} | |
80 | + members_list.collect{|person| person.add_role(@role, profile)} | |
81 | + elsif params[:assign_role_by].eql? "roles" | |
82 | + members = profile.members_by_role(selected_role) | |
83 | + replace_role(members, selected_role, @role, profile) | |
84 | + else | |
85 | + session[:notice] = _("Error") | |
86 | + end | |
87 | + redirect_to :action => 'index' | |
88 | + end | |
89 | + | |
90 | + protected | |
91 | + | |
92 | + def append_roles(members, roles, profile) | |
93 | + members.each do |person| | |
94 | + all_roles = person.find_roles(profile).map(&:role) + roles | |
95 | + person.define_roles(all_roles, profile) | |
96 | + end | |
97 | + end | |
98 | + | |
99 | + def all_roles(environment, profile) | |
100 | + Profile::Roles.organization_member_roles(environment.id) + profile.custom_roles | |
101 | + end | |
102 | + | |
103 | + def replace_roles(members, roles, profile) | |
104 | + members.each do |person| | |
105 | + person.define_roles(roles, profile) | |
106 | + end | |
107 | + end | |
108 | + | |
109 | + def replace_role(members, role, new_role, profile) | |
110 | + members.each do |person| | |
111 | + person.remove_role(role, profile) | |
112 | + person.add_role(new_role, profile) | |
113 | + end | |
114 | + end | |
115 | + | |
116 | +end | ... | ... |
app/controllers/my_profile/tasks_controller.rb
1 | 1 | class TasksController < MyProfileController |
2 | 2 | |
3 | - protect 'perform_task', :profile | |
4 | - | |
3 | + protect [:perform_task, :view_tasks], :profile, :only => [:index, :save_tags, :search_tags] | |
4 | + protect :perform_task, :profile, :only => [:processed, :change_responsible, :close, :new, :list_requested, :ticket_details, :search_tags] | |
5 | + | |
5 | 6 | def index |
6 | - @filter = params[:filter_type].blank? ? nil : params[:filter_type] | |
7 | + @rejection_email_templates = profile.email_templates.find_all_by_template_type(:task_rejection) | |
8 | + @acceptance_email_templates = profile.email_templates.find_all_by_template_type(:task_acceptance) | |
9 | + | |
10 | + @filter_type = params[:filter_type].presence | |
11 | + @filter_text = params[:filter_text].presence | |
12 | + @filter_responsible = params[:filter_responsible] | |
13 | + @filter_tags = params[:filter_tags] | |
14 | + | |
7 | 15 | @task_types = Task.pending_types_for(profile) |
8 | - @tasks = Task.to(profile).without_spam.pending.of(@filter).order_by('created_at', 'asc').paginate(:per_page => Task.per_page, :page => params[:page]) | |
16 | + @task_tags = [OpenStruct.new(:name => _('All'), :id => nil) ] + Task.all_tags | |
17 | + | |
18 | + @tasks = Task.pending_all(profile, @filter_type, @filter_text).order_by('created_at', 'asc') | |
19 | + @tasks = @tasks.where(:responsible_id => @filter_responsible.to_i != -1 ? @filter_responsible : nil) if @filter_responsible.present? | |
20 | + @tasks = @tasks.tagged_with(@filter_tags, any: true) if @filter_tags.present? | |
21 | + @tasks = @tasks.paginate(:per_page => Task.per_page, :page => params[:page]) | |
22 | + | |
9 | 23 | @failed = params ? params[:failed] : {} |
24 | + | |
25 | + @responsible_candidates = profile.members.by_role(profile.roles.reject {|r| !r.has_permission?('perform_task') && !r.has_permission?('view_tasks')}) if profile.organization? | |
26 | + | |
27 | + @view_only = !current_person.has_permission?(:perform_task, profile) | |
10 | 28 | end |
11 | 29 | |
12 | 30 | def processed |
13 | - @tasks = Task.to(profile).without_spam.closed.sort_by(&:created_at) | |
31 | + @tasks = Task.to(profile).without_spam.closed.order('tasks.created_at DESC') | |
32 | + @filter = params[:filter] || {} | |
33 | + @tasks = filter_tasks(@filter, @tasks) | |
34 | + @tasks = @tasks.paginate(:per_page => Task.per_page, :page => params[:page]) | |
35 | + @task_types = Task.closed_types_for(profile) | |
36 | + end | |
37 | + | |
38 | + def change_responsible | |
39 | + task = profile.tasks.find(params[:task_id]) | |
40 | + | |
41 | + if task.responsible.present? && task.responsible.id != params[:old_responsible_id].to_i | |
42 | + return render :json => {:notice => _('Task already assigned!'), :success => false, :current_responsible => task.responsible.id} | |
43 | + end | |
44 | + | |
45 | + responsible = profile.members.find(params[:responsible_id]) if params[:responsible_id].present? | |
46 | + task.responsible = responsible | |
47 | + task.save! | |
48 | + render :json => {:notice => _('Task responsible successfully updated!'), :success => true, :new_responsible => {:id => responsible.present? ? responsible.id : nil}} | |
14 | 49 | end |
15 | 50 | |
16 | 51 | VALID_DECISIONS = [ 'finish', 'cancel', 'skip' ] |
17 | 52 | |
18 | 53 | def close |
19 | 54 | failed = {} |
55 | + save = false | |
20 | 56 | |
21 | 57 | if params[:tasks] |
22 | 58 | params[:tasks].each do |id, value| |
23 | 59 | decision = value[:decision] |
24 | - if request.post? && VALID_DECISIONS.include?(decision) && id && decision != 'skip' | |
60 | + | |
61 | + if value[:task].is_a?(Hash) && value[:task][:tag_list] | |
62 | + | |
25 | 63 | task = profile.find_in_all_tasks(id) |
26 | - begin | |
27 | - task.update_attributes(value[:task]) | |
28 | - task.send(decision) | |
29 | - rescue Exception => ex | |
30 | - message = "#{task.title} (#{task.requestor ? task.requestor.name : task.author_name})" | |
31 | - failed[ex.message] ? failed[ex.message] << message : failed[ex.message] = [message] | |
64 | + task.tag_list = value[:task][:tag_list] | |
65 | + value[:task].delete('tag_list') | |
66 | + | |
67 | + save = true | |
68 | + end | |
69 | + | |
70 | + if request.post? | |
71 | + if VALID_DECISIONS.include?(decision) && id && decision != 'skip' | |
72 | + task ||= profile.find_in_all_tasks(id) | |
73 | + begin | |
74 | + task.update_attributes(value[:task]) | |
75 | + task.send(decision, current_person) | |
76 | + rescue Exception => ex | |
77 | + message = "#{task.title} (#{task.requestor ? task.requestor.name : task.author_name})" | |
78 | + failed[ex.message] ? failed[ex.message] << message : failed[ex.message] = [message] | |
79 | + end | |
80 | + elsif save | |
81 | + task.save! | |
32 | 82 | end |
33 | 83 | end |
34 | 84 | end |
35 | 85 | end |
36 | 86 | |
37 | 87 | url = { :action => 'index' } |
88 | + | |
38 | 89 | if failed.blank? |
39 | 90 | session[:notice] = _("All decisions were applied successfully.") |
40 | 91 | else |
... | ... | @@ -65,4 +116,79 @@ class TasksController < MyProfileController |
65 | 116 | @ticket = Ticket.find(:first, :conditions => ['(requestor_id = ? or target_id = ?) and id = ?', profile.id, profile.id, params[:id]]) |
66 | 117 | end |
67 | 118 | |
119 | + def search_tasks | |
120 | + filter_type = params[:filter_type].presence | |
121 | + filter_text = params[:filter_text].presence | |
122 | + result = Task.pending_all(profile,filter_type, filter_text) | |
123 | + | |
124 | + render :json => result.map { |task| {:label => task.data[:name], :value => task.data[:name]} } | |
125 | + end | |
126 | + | |
127 | + def save_tags | |
128 | + if request.post? && params[:tag_list] | |
129 | + result = { | |
130 | + success: false, | |
131 | + message: _('Error to save tags. Please, contact the system admin') | |
132 | + } | |
133 | + | |
134 | + ActsAsTaggableOn.remove_unused_tags = true | |
135 | + | |
136 | + task = profile.tasks.find_by_id(params[:task_id]) | |
137 | + | |
138 | + if task && task.update_attributes(:tag_list => params[:tag_list]) | |
139 | + result[:success] = true | |
140 | + end | |
141 | + end | |
142 | + | |
143 | + render json: result | |
144 | + end | |
145 | + | |
146 | + # FIXME make this test | |
147 | + # Should not search for article tasks | |
148 | + # Should not search for other profile tags | |
149 | + # Should search only task tags | |
150 | + # Should check the permissions | |
151 | + | |
152 | + def search_tags | |
153 | + | |
154 | + arg = params[:term].downcase | |
155 | + | |
156 | + result = ActsAsTaggableOn::Tag.find(:all, :conditions => ['LOWER(name) LIKE ?', "%#{arg}%"]) | |
157 | + | |
158 | + render :text => prepare_to_token_input_by_label(result).to_json, :content_type => 'application/json' | |
159 | + end | |
160 | + | |
161 | + protected | |
162 | + | |
163 | + def filter_by_closed_date(filter, tasks) | |
164 | + filter[:closed_from] = Date.parse(filter[:closed_from]) unless filter[:closed_from].blank? | |
165 | + filter[:closed_until] = Date.parse(filter[:closed_until]) unless filter[:closed_until].blank? | |
166 | + | |
167 | + tasks = tasks.where('tasks.end_date >= ?', filter[:closed_from].beginning_of_day) unless filter[:closed_from].blank? | |
168 | + tasks = tasks.where('tasks.end_date <= ?', filter[:closed_until].end_of_day) unless filter[:closed_until].blank? | |
169 | + tasks | |
170 | + end | |
171 | + | |
172 | + def filter_by_creation_date(filter, tasks) | |
173 | + filter[:created_from] = Date.parse(filter[:created_from]) unless filter[:created_from].blank? | |
174 | + filter[:created_until] = Date.parse(filter[:created_until]) unless filter[:created_until].blank? | |
175 | + | |
176 | + tasks = tasks.where('tasks.created_at >= ?', filter[:created_from].beginning_of_day) unless filter[:created_from].blank? | |
177 | + tasks = tasks.where('tasks.created_at <= ?', filter[:created_until].end_of_day) unless filter[:created_until].blank? | |
178 | + tasks | |
179 | + end | |
180 | + | |
181 | + def filter_tasks(filter, tasks) | |
182 | + tasks = tasks.includes(:requestor, :closed_by) | |
183 | + tasks = tasks.of(filter[:type].presence) | |
184 | + tasks = tasks.where(:status => filter[:status]) unless filter[:status].blank? | |
185 | + tasks = filter_by_creation_date(filter, tasks) | |
186 | + tasks = filter_by_closed_date(filter, tasks) | |
187 | + | |
188 | + tasks = tasks.like('profiles.name', filter[:requestor]) unless filter[:requestor].blank? | |
189 | + tasks = tasks.like('closed_bies_tasks.name', filter[:closed_by]) unless filter[:closed_by].blank? | |
190 | + tasks = tasks.like('tasks.data', filter[:text]) unless filter[:text].blank? | |
191 | + tasks | |
192 | + end | |
193 | + | |
68 | 194 | end | ... | ... |
app/controllers/public/account_controller.rb
... | ... | @@ -16,7 +16,7 @@ class AccountController < ApplicationController |
16 | 16 | def activate |
17 | 17 | @user = User.find_by_activation_code(params[:activation_code]) if params[:activation_code] |
18 | 18 | if @user |
19 | - unless @user.environment.enabled?('admin_must_approve_new_users') | |
19 | + unless @user.environment.enabled?('admin_must_approve_new_users') | |
20 | 20 | if @user.activate |
21 | 21 | @message = _("Your account has been activated, now you can log in!") |
22 | 22 | check_redirection |
... | ... | @@ -30,7 +30,7 @@ class AccountController < ApplicationController |
30 | 30 | @user.activation_code = nil |
31 | 31 | @user.save! |
32 | 32 | redirect_to :controller => :home |
33 | - end | |
33 | + end | |
34 | 34 | end |
35 | 35 | else |
36 | 36 | session[:notice] = _("It looks like you're trying to activate an account. Perhaps have already activated this account?") |
... | ... | @@ -50,10 +50,12 @@ class AccountController < ApplicationController |
50 | 50 | |
51 | 51 | if logged_in? |
52 | 52 | check_join_in_community(self.current_user) |
53 | + | |
53 | 54 | if params[:remember_me] == "1" |
54 | 55 | self.current_user.remember_me |
55 | - cookies[:auth_token] = { :value => self.current_user.remember_token , :expires => self.current_user.remember_token_expires_at } | |
56 | + cookies[:auth_token] = {value: self.current_user.remember_token, expires: self.current_user.remember_token_expires_at} | |
56 | 57 | end |
58 | + | |
57 | 59 | if redirect? |
58 | 60 | go_to_initial_page |
59 | 61 | session[:notice] = _("Logged in successfully") |
... | ... | @@ -77,6 +79,13 @@ class AccountController < ApplicationController |
77 | 79 | render :text => { :ok=>true, :key=>key }.to_json |
78 | 80 | end |
79 | 81 | |
82 | + def custom_fields_for_template | |
83 | + custom_fields ||= environment.people.templates.find(params[:template_id]).custom_fields.map { |k,v| | |
84 | + { :name => k, :title => v[:title] } if v['signup'] | |
85 | + }.compact | |
86 | + render :text => {:ok => true, :custom_fields => custom_fields}.to_json | |
87 | + end | |
88 | + | |
80 | 89 | # action to register an user to the application |
81 | 90 | def signup |
82 | 91 | if @plugins.dispatch(:allow_user_registration).include?(false) |
... | ... | @@ -92,6 +101,7 @@ class AccountController < ApplicationController |
92 | 101 | @invitation_code = params[:invitation_code] |
93 | 102 | begin |
94 | 103 | @user = User.new(params[:user]) |
104 | + @user.session = session | |
95 | 105 | @user.terms_of_use = environment.terms_of_use |
96 | 106 | @user.environment = environment |
97 | 107 | @terms_of_use = environment.terms_of_use |
... | ... | @@ -358,11 +368,11 @@ class AccountController < ApplicationController |
358 | 368 | end |
359 | 369 | |
360 | 370 | def get_signup_start_time |
361 | - Rails.cache.read params[:signup_time_key] | |
371 | + Rails.cache.read params[:signup_time_key] if params[:signup_time_key].present? | |
362 | 372 | end |
363 | 373 | |
364 | 374 | def clear_signup_start_time |
365 | - Rails.cache.delete params[:signup_time_key] if params[:signup_time_key] | |
375 | + Rails.cache.delete params[:signup_time_key] if params[:signup_time_key].present? | |
366 | 376 | end |
367 | 377 | |
368 | 378 | def may_be_a_bot |
... | ... | @@ -435,7 +445,7 @@ class AccountController < ApplicationController |
435 | 445 | end |
436 | 446 | |
437 | 447 | def go_to_signup_initial_page |
438 | - check_redirection_options(user, user.environment.redirection_after_signup, user.url) | |
448 | + check_redirection_options user, user.environment.redirection_after_signup, user.url, signup: true | |
439 | 449 | end |
440 | 450 | |
441 | 451 | def redirect_if_logged_in |
... | ... | @@ -455,8 +465,11 @@ class AccountController < ApplicationController |
455 | 465 | |
456 | 466 | protected |
457 | 467 | |
458 | - def check_redirection_options(user, condition, default) | |
459 | - case condition | |
468 | + def check_redirection_options user, condition, default, options={} | |
469 | + if options[:signup] and target = session.delete(:after_signup_redirect_to) | |
470 | + redirect_to target | |
471 | + else | |
472 | + case condition | |
460 | 473 | when 'keep_on_same_page' |
461 | 474 | redirect_back_or_default(user.admin_url) |
462 | 475 | when 'site_homepage' |
... | ... | @@ -469,8 +482,11 @@ class AccountController < ApplicationController |
469 | 482 | redirect_to user.admin_url |
470 | 483 | when 'welcome_page' |
471 | 484 | redirect_to :controller => :home, :action => :welcome, :template_id => (user.template && user.template.id) |
472 | - else | |
473 | - redirect_back_or_default(default) | |
485 | + when 'custom_url' | |
486 | + if (url = user.custom_url_redirection).present? then redirect_to url else redirect_back_or_default default end | |
487 | + else | |
488 | + redirect_back_or_default(default) | |
489 | + end | |
474 | 490 | end |
475 | 491 | end |
476 | 492 | ... | ... |
... | ... | @@ -0,0 +1,19 @@ |
1 | +class ApiController < PublicController | |
2 | + | |
3 | + no_design_blocks | |
4 | + | |
5 | + helper_method :endpoints | |
6 | + | |
7 | + def index | |
8 | + end | |
9 | + | |
10 | + def playground | |
11 | + end | |
12 | + | |
13 | + private | |
14 | + | |
15 | + def endpoints | |
16 | + Noosfero::API::API.endpoints(environment) | |
17 | + end | |
18 | + | |
19 | +end | ... | ... |
app/controllers/public/chat_controller.rb
... | ... | @@ -2,6 +2,7 @@ class ChatController < PublicController |
2 | 2 | |
3 | 3 | before_filter :login_required |
4 | 4 | before_filter :check_environment_feature |
5 | + before_filter :can_send_message, :only => :register_message | |
5 | 6 | |
6 | 7 | def start_session |
7 | 8 | login = user.jid |
... | ... | @@ -54,6 +55,16 @@ class ChatController < PublicController |
54 | 55 | end |
55 | 56 | end |
56 | 57 | |
58 | + def avatars | |
59 | + profiles = environment.profiles.where(:identifier => params[:profiles]) | |
60 | + avatar_map = profiles.inject({}) do |result, profile| | |
61 | + result[profile.identifier] = profile_icon(profile, :minor) | |
62 | + result | |
63 | + end | |
64 | + | |
65 | + render_json avatar_map | |
66 | + end | |
67 | + | |
57 | 68 | def update_presence_status |
58 | 69 | if request.xhr? |
59 | 70 | current_user.update_attributes({:chat_status_at => DateTime.now}.merge(params[:status] || {})) |
... | ... | @@ -62,11 +73,17 @@ class ChatController < PublicController |
62 | 73 | end |
63 | 74 | |
64 | 75 | def save_message |
65 | - to = environment.profiles.find_by_identifier(params[:to]) | |
66 | - body = params[:body] | |
67 | - | |
68 | - ChatMessage.create!(:to => to, :from => user, :body => body) | |
69 | - render :text => 'ok' | |
76 | + if request.post? | |
77 | + to = environment.profiles.where(:identifier => params[:to]).first | |
78 | + body = params[:body] | |
79 | + | |
80 | + begin | |
81 | + ChatMessage.create!(:to => to, :from => user, :body => body) | |
82 | + return render_json({:status => 0}) | |
83 | + rescue Exception => exception | |
84 | + return render_json({:status => 3, :message => exception.to_s, :backtrace => exception.backtrace}) | |
85 | + end | |
86 | + end | |
70 | 87 | end |
71 | 88 | |
72 | 89 | def recent_messages |
... | ... | @@ -90,8 +107,9 @@ class ChatController < PublicController |
90 | 107 | end |
91 | 108 | |
92 | 109 | def recent_conversations |
93 | - conversations_order = ActiveRecord::Base.connection.execute("select profiles.identifier from profiles inner join (select distinct r.id as id, MAX(r.created_at) as created_at from (select from_id, to_id, created_at, (case when from_id=#{user.id} then to_id else from_id end) as id from chat_messages where from_id=#{user.id} or to_id=#{user.id}) as r group by id order by created_at desc, id) as t on profiles.id=t.id order by t.created_at desc").entries.map {|e| e['identifier']} | |
94 | - render :json => {:order => conversations_order.reverse, :domain => environment.default_hostname.gsub('.','-')}.to_json | |
110 | + profiles = Profile.find_by_sql("select profiles.* from profiles inner join (select distinct r.id as id, MAX(r.created_at) as created_at from (select from_id, to_id, created_at, (case when from_id=#{user.id} then to_id else from_id end) as id from chat_messages where from_id=#{user.id} or to_id=#{user.id}) as r group by id order by created_at desc, id) as t on profiles.id=t.id order by t.created_at desc") | |
111 | + jids = profiles.map(&:jid).reverse | |
112 | + render :json => jids.to_json | |
95 | 113 | end |
96 | 114 | |
97 | 115 | #TODO Ideally this is done through roster table on ejabberd. |
... | ... | @@ -108,4 +126,14 @@ class ChatController < PublicController |
108 | 126 | end |
109 | 127 | end |
110 | 128 | |
129 | + def can_send_message | |
130 | + return render_json({:status => 1, :message => 'Missing parameters!'}) if params[:from].nil? || params[:to].nil? || params[:message].nil? | |
131 | + return render_json({:status => 2, :message => 'You can not send message as another user!'}) if params[:from] != user.jid | |
132 | + # TODO Maybe register the jid in a table someday to avoid this below | |
133 | + return render_json({:status => 3, :messsage => 'You can not send messages to strangers!'}) if user.friends.where(:identifier => params[:to].split('@').first).blank? | |
134 | + end | |
135 | + | |
136 | + def render_json(result) | |
137 | + render :text => result.to_json | |
138 | + end | |
111 | 139 | end | ... | ... |
app/controllers/public/contact_controller.rb
... | ... | @@ -6,8 +6,9 @@ class ContactController < PublicController |
6 | 6 | def new |
7 | 7 | @contact = build_contact |
8 | 8 | if request.post? && params[:confirm] == 'true' |
9 | - @contact.city = (!params[:city].blank? && City.exists?(params[:city])) ? City.find(params[:city]).name : nil | |
10 | - @contact.state = (!params[:state].blank? && State.exists?(params[:state])) ? State.find(params[:state]).name : nil | |
9 | + # updated to use hash as argument to exists? to avoid sql injection vunerabillity (http://brakemanscanner.org/docs/warning_types/sql_injection/) | |
10 | + @contact.city = (!params[:city].blank? && City.exists?(:id => params[:city])) ? City.find(params[:city]).name : nil | |
11 | + @contact.state = (!params[:state].blank? && State.exists?(:id => params[:state])) ? State.find(params[:state]).name : nil | |
11 | 12 | if @contact.deliver |
12 | 13 | session[:notice] = _('Contact successfully sent') |
13 | 14 | redirect_to :action => 'new' | ... | ... |
app/controllers/public/content_viewer_controller.rb
... | ... | @@ -15,9 +15,10 @@ class ContentViewerController < ApplicationController |
15 | 15 | path = get_path(params[:page], params[:format]) |
16 | 16 | |
17 | 17 | @version = params[:version].to_i |
18 | + @npage = params[:npage] || '1' | |
18 | 19 | |
19 | 20 | if path.blank? |
20 | - @page = profile.home_page | |
21 | + @page = profile.home_page | |
21 | 22 | return if redirected_to_profile_index |
22 | 23 | else |
23 | 24 | @page = profile.articles.find_by_path(path) |
... | ... | @@ -74,7 +75,7 @@ class ContentViewerController < ApplicationController |
74 | 75 | render :action => 'slideshow', :layout => 'slideshow' |
75 | 76 | return |
76 | 77 | end |
77 | - render :view_page, :formats => [:html] | |
78 | + render @page.view_page, :formats => [:html] | |
78 | 79 | end |
79 | 80 | |
80 | 81 | def versions_diff |
... | ... | @@ -125,21 +126,23 @@ class ContentViewerController < ApplicationController |
125 | 126 | helper_method :pass_without_comment_captcha? |
126 | 127 | |
127 | 128 | def allow_access_to_page(path) |
128 | - allowed = true | |
129 | 129 | if @page.nil? # page not found, give error |
130 | 130 | render_not_found(path) |
131 | - allowed = false | |
132 | - elsif !@page.display_to?(user) | |
133 | - if !profile.public? | |
131 | + return false | |
132 | + end | |
133 | + | |
134 | + unless @page.display_to?(user) | |
135 | + if !profile.visible? || profile.secret? || (user && user.follows?(profile)) || user.blank? | |
136 | + render_access_denied | |
137 | + else #!profile.public? | |
134 | 138 | private_profile_partial_parameters |
135 | 139 | render :template => 'profile/_private_profile', :status => 403, :formats => [:html] |
136 | - allowed = false | |
137 | - else #if !profile.visible? | |
138 | - render_access_denied | |
139 | - allowed = false | |
140 | 140 | end |
141 | + | |
142 | + return false | |
141 | 143 | end |
142 | - allowed | |
144 | + | |
145 | + return true | |
143 | 146 | end |
144 | 147 | |
145 | 148 | def user_is_a_bot? |
... | ... | @@ -184,7 +187,7 @@ class ContentViewerController < ApplicationController |
184 | 187 | if @page.forum? && @page.has_terms_of_use && terms_accepted == "true" |
185 | 188 | @page.add_agreed_user(user) |
186 | 189 | end |
187 | - end | |
190 | + end | |
188 | 191 | |
189 | 192 | def is_a_forum_topic? (page) |
190 | 193 | return (!@page.parent.nil? && @page.parent.forum?) | ... | ... |
app/controllers/public/home_controller.rb
app/controllers/public/invite_controller.rb
... | ... | @@ -62,20 +62,36 @@ class InviteController < PublicController |
62 | 62 | redirect_to :action => 'invite_friends' |
63 | 63 | end |
64 | 64 | |
65 | + #Invite or add member without create a task | |
66 | + #if logged user is admin of environment | |
65 | 67 | def invite_registered_friend |
68 | + | |
69 | + if !params['q'].present? || !request.post? | |
70 | + | |
71 | + redirect_to :action => 'invite_friends' | |
72 | + session[:notice] = _('Please enter a valid profile.') | |
73 | + | |
74 | + return | |
75 | + end | |
76 | + | |
66 | 77 | contacts_to_invite = params['q'].split(',') |
67 | - if !contacts_to_invite.empty? && request.post? | |
78 | + | |
79 | + if user.is_admin? && profile.community? | |
80 | + | |
81 | + Delayed::Job.enqueue AddMembersJob.new contacts_to_invite, profile.id, locale | |
82 | + | |
83 | + session[:notice] = _('This friends was added!') | |
84 | + else | |
68 | 85 | Delayed::Job.enqueue InvitationJob.new(user.id, contacts_to_invite, '', profile.id, nil, locale) |
69 | 86 | session[:notice] = _('Your invitations are being sent.') |
70 | - if profile.person? | |
71 | - redirect_to :controller => 'profile', :action => 'friends' | |
72 | - else | |
73 | - redirect_to :controller => 'profile', :action => 'members' | |
74 | - end | |
87 | + end | |
88 | + | |
89 | + if profile.person? | |
90 | + redirect_to :controller => 'profile', :action => 'friends' | |
75 | 91 | else |
76 | - redirect_to :action => 'invite_friends' | |
77 | - session[:notice] = _('Please enter a valid profile.') | |
92 | + redirect_to :controller => 'profile', :action => 'members' | |
78 | 93 | end |
94 | + | |
79 | 95 | end |
80 | 96 | |
81 | 97 | def search | ... | ... |
app/controllers/public/profile_controller.rb
... | ... | @@ -6,6 +6,7 @@ class ProfileController < PublicController |
6 | 6 | before_filter :login_required, :only => [:add, :join, :leave, :unblock, :leave_scrap, :remove_scrap, :remove_activity, :view_more_activities, :view_more_network_activities, :report_abuse, :register_report, :leave_comment_on_activity, :send_mail] |
7 | 7 | |
8 | 8 | helper TagsHelper |
9 | + helper ActionTrackerHelper | |
9 | 10 | |
10 | 11 | protect 'send_mail_to_members', :profile, :only => [:send_mail] |
11 | 12 | |
... | ... | @@ -201,7 +202,10 @@ class ProfileController < PublicController |
201 | 202 | |
202 | 203 | def more_comments |
203 | 204 | profile_filter = @profile.person? ? {:user_id => @profile} : {:target_id => @profile} |
204 | - activity = ActionTracker::Record.find(:first, :conditions => {:id => params[:activity]}.merge(profile_filter)) | |
205 | + activity = ActionTracker::Record.where(:id => params[:activity]) | |
206 | + activity = activity.where(profile_filter) if !logged_in? || !current_person.follows?(@profile) | |
207 | + activity = activity.first | |
208 | + | |
205 | 209 | comments_count = activity.comments.count |
206 | 210 | comment_page = (params[:comment_page] || 1).to_i |
207 | 211 | comments_per_page = 5 |
... | ... | @@ -353,6 +357,7 @@ class ProfileController < PublicController |
353 | 357 | |
354 | 358 | def send_mail |
355 | 359 | @mailing = profile.mailings.build(params[:mailing]) |
360 | + @email_templates = profile.email_templates.find_all_by_template_type(:organization_members) | |
356 | 361 | if request.post? |
357 | 362 | @mailing.locale = locale |
358 | 363 | @mailing.person = user | ... | ... |
app/controllers/public/search_controller.rb
... | ... | @@ -95,10 +95,10 @@ class SearchController < PublicController |
95 | 95 | |
96 | 96 | def events |
97 | 97 | if params[:year].blank? && params[:year].blank? && params[:day].blank? |
98 | - @date = Date.today | |
98 | + @date = DateTime.now | |
99 | 99 | else |
100 | - year = (params[:year] ? params[:year].to_i : Date.today.year) | |
101 | - month = (params[:month] ? params[:month].to_i : Date.today.month) | |
100 | + year = (params[:year] ? params[:year].to_i : DateTime.now.year) | |
101 | + month = (params[:month] ? params[:month].to_i : DateTime.now.month) | |
102 | 102 | day = (params[:day] ? params[:day].to_i : 1) |
103 | 103 | @date = build_date(year, month, day) |
104 | 104 | end |
... | ... | @@ -109,9 +109,7 @@ class SearchController < PublicController |
109 | 109 | @events = @category ? |
110 | 110 | environment.events.by_day(@date).in_category(Category.find(@category_id)).paginate(:per_page => per_page, :page => params[:page]) : |
111 | 111 | environment.events.by_day(@date).paginate(:per_page => per_page, :page => params[:page]) |
112 | - end | |
113 | - | |
114 | - if params[:year] || params[:month] | |
112 | + elsif params[:year] || params[:month] | |
115 | 113 | @events = @category ? |
116 | 114 | environment.events.by_month(@date).in_category(Category.find(@category_id)).paginate(:per_page => per_page, :page => params[:page]) : |
117 | 115 | environment.events.by_month(@date).paginate(:per_page => per_page, :page => params[:page]) | ... | ... |
app/controllers/public_controller.rb
... | ... | @@ -0,0 +1,94 @@ |
1 | +module ActionTrackerHelper | |
2 | + | |
3 | + def create_article_description ta | |
4 | + _('published an article: %{title}') % { title: link_to(truncate(ta.get_name), ta.get_url) } | |
5 | + end | |
6 | + | |
7 | + def new_friendship_description ta | |
8 | + n_('has made 1 new friend:<br />%{name}', 'has made %{num} new friends:<br />%{name}', ta.get_friend_name.size) % { | |
9 | + num: ta.get_friend_name.size, | |
10 | + name: ta.collect_group_with_index(:friend_name) do |n,i| | |
11 | + link_to image_tag(ta.get_friend_profile_custom_icon[i] || default_or_themed_icon("/images/icons-app/person-icon.png")), | |
12 | + ta.get_friend_url[i], title: n | |
13 | + end.join | |
14 | + } | |
15 | + end | |
16 | + | |
17 | + def join_community_description ta | |
18 | + n_('has joined 1 community:<br />%{name}', 'has joined %{num} communities:<br />%{name}', ta.get_resource_name.size) % { | |
19 | + num: ta.get_resource_name.size, | |
20 | + name: ta.collect_group_with_index(:resource_name) do |n,i| | |
21 | + link_to image_tag(ta.get_resource_profile_custom_icon[i] || default_or_themed_icon("/images/icons-app/community-icon.png")), | |
22 | + ta.get_resource_url[i], title: n | |
23 | + end.join | |
24 | + } | |
25 | + end | |
26 | + | |
27 | + def add_member_in_community_description ta | |
28 | + _('has joined the community.') | |
29 | + end | |
30 | + | |
31 | + def upload_image_description ta | |
32 | + total = ta.get_view_url.size | |
33 | + (n_('uploaded 1 image', 'uploaded %d images', total) % total) + | |
34 | + tag(:br) + | |
35 | + ta.collect_group_with_index(:thumbnail_path) do |t,i| | |
36 | + if total == 1 | |
37 | + link_to image_tag(t), ta.get_view_url[i], class: 'upimg' | |
38 | + else | |
39 | + pos = total-i; | |
40 | + morethen2 = pos>2 ? 'morethen2' : '' | |
41 | + morethen5 = pos>5 ? 'morethen5' : '' | |
42 | + t = t.gsub(/(.*)(display)(.*)/, '\\1thumb\\3') | |
43 | + | |
44 | + link_to ' '.html_safe, ta.get_view_url[i], | |
45 | + style: "background-image:url(#{t})", | |
46 | + class: "upimg pos#{pos} #{morethen2} #{morethen5}" | |
47 | + end | |
48 | + end.reverse.join + | |
49 | + if total <= 5 then ''.html_safe else content_tag :span, '…'.html_safe, | |
50 | + class: 'more', onclick: "this.parentNode.className+=' show-all'" end + | |
51 | + tag(:br, style: 'clear: both') | |
52 | + end | |
53 | + | |
54 | + def reply_scrap_description ta | |
55 | + _('sent a message to %{receiver}: <br /> "%{message}"') % { | |
56 | + receiver: link_to(ta.get_receiver_name, ta.get_receiver_url), | |
57 | + message: auto_link_urls(ta.get_content) | |
58 | + } | |
59 | + end | |
60 | + | |
61 | + alias :leave_scrap_description :reply_scrap_description | |
62 | + alias :reply_scrap_on_self_description :reply_scrap_description | |
63 | + | |
64 | + def leave_scrap_to_self_description ta | |
65 | + _('wrote: <br /> "%{text}"') % { | |
66 | + text: auto_link_urls(ta.get_content) | |
67 | + } | |
68 | + end | |
69 | + | |
70 | + def create_product_description | |
71 | + _('created the product %{title}') % { | |
72 | + title: link_to(truncate(ta.get_name), ta.get_url), | |
73 | + } | |
74 | + end | |
75 | + | |
76 | + def update_product_description | |
77 | + _('updated the product %{title}') % { | |
78 | + title: link_to(truncate(ta.get_name), ta.get_url), | |
79 | + } | |
80 | + end | |
81 | + | |
82 | + def remove_product_description | |
83 | + _('removed the product %{title}') % { | |
84 | + title: truncate(ta.get_name), | |
85 | + } | |
86 | + end | |
87 | + | |
88 | + def favorite_enterprise_description ta | |
89 | + _('favorited enterprise %{title}') % { | |
90 | + title: link_to(truncate(ta.get_enterprise_name), ta.get_enterprise_url), | |
91 | + } | |
92 | + end | |
93 | + | |
94 | +end | ... | ... |
app/helpers/application_helper.rb
... | ... | @@ -44,6 +44,8 @@ module ApplicationHelper |
44 | 44 | |
45 | 45 | include PluginsHelper |
46 | 46 | |
47 | + include TaskHelper | |
48 | + | |
47 | 49 | def locale |
48 | 50 | (@page && !@page.language.blank?) ? @page.language : FastGettext.locale |
49 | 51 | end |
... | ... | @@ -707,6 +709,24 @@ module ApplicationHelper |
707 | 709 | javascript_include_tag script if script |
708 | 710 | end |
709 | 711 | |
712 | + def template_path | |
713 | + if profile.nil? | |
714 | + "/designs/templates/#{environment.layout_template}" | |
715 | + else | |
716 | + "/designs/templates/#{profile.layout_template}" | |
717 | + end | |
718 | + end | |
719 | + | |
720 | + def template_javascript_src | |
721 | + script = File.join template_path, '/javascripts/template.js' | |
722 | + script if File.exists? File.join(Rails.root, 'public', script) | |
723 | + end | |
724 | + | |
725 | + def templete_javascript_ng | |
726 | + script = template_javascript_src | |
727 | + javascript_include_tag script if script | |
728 | + end | |
729 | + | |
710 | 730 | def file_field_or_thumbnail(label, image, i) |
711 | 731 | display_form_field label, ( |
712 | 732 | render :partial => (image && image.valid? ? 'shared/show_thumbnail' : 'shared/change_image'), |
... | ... | @@ -853,7 +873,7 @@ module ApplicationHelper |
853 | 873 | field_html += capture(&block) |
854 | 874 | end |
855 | 875 | |
856 | - if controller.action_name == 'signup' || controller.action_name == 'new_community' || (controller.controller_name == "enterprise_registration" && controller.action_name == 'index') | |
876 | + if controller.action_name == 'signup' || controller.action_name == 'new_community' || (controller.controller_name == "enterprise_registration" && controller.action_name == 'index') || (controller.controller_name == 'home' && controller.action_name == 'index' && user.nil?) | |
857 | 877 | if profile.signup_fields.include?(name) |
858 | 878 | result = field_html |
859 | 879 | end |
... | ... | @@ -913,6 +933,19 @@ module ApplicationHelper |
913 | 933 | article_helper.cms_label_for_edit |
914 | 934 | end |
915 | 935 | |
936 | + def label_for_clone_article(article) | |
937 | + translated_types = { | |
938 | + Folder => _('Folder'), | |
939 | + Blog => _('Blog'), | |
940 | + Event => _('Event'), | |
941 | + Forum => _('Forum') | |
942 | + } | |
943 | + | |
944 | + translated_type = translated_types[article.class] || _('Article') | |
945 | + | |
946 | + _('Clone %s') % translated_type | |
947 | + end | |
948 | + | |
916 | 949 | def add_rss_feed_to_head(title, url) |
917 | 950 | content_for :feeds do |
918 | 951 | tag(:link, :rel => 'alternate', :type => 'application/rss+xml', :title => title, :href => url_for(url)) |
... | ... | @@ -1151,10 +1184,10 @@ module ApplicationHelper |
1151 | 1184 | pending_tasks_count = '' |
1152 | 1185 | count = user ? Task.to(user).pending.count : -1 |
1153 | 1186 | if count > 0 |
1154 | - pending_tasks_count = link_to(count.to_s, user.tasks_url, :id => 'pending-tasks-count', :title => _("Manage your pending tasks")) | |
1187 | + pending_tasks_count = link_to("<i class=\"icon-menu-tasks\"></i><span class=\"task-count\">#{count}</span>", user.tasks_url, :id => 'pending-tasks-count', :title => _("Manage your pending tasks")) | |
1155 | 1188 | end |
1156 | 1189 | |
1157 | - (_("<span class='welcome'>Welcome,</span> %s") % link_to("<i style='background-image:url(#{user.profile_custom_icon(gravatar_default)})'></i><strong>#{user.identifier}</strong>", user.public_profile_url, :id => "homepage-link", :title => _('Go to your homepage'))) + | |
1190 | + (_("<span class='welcome'>Welcome,</span> %s") % link_to("<i style='background-image:url(#{user.profile_custom_icon(gravatar_default)})'></i><strong>#{user.identifier}</strong>", user.url, :id => "homepage-link", :title => _('Go to your homepage'))) + | |
1158 | 1191 | render_environment_features(:usermenu) + |
1159 | 1192 | admin_link + |
1160 | 1193 | manage_enterprises + |
... | ... | @@ -1173,7 +1206,8 @@ module ApplicationHelper |
1173 | 1206 | end |
1174 | 1207 | |
1175 | 1208 | def expandable_text_area(object_name, method, text_area_id, options = {}) |
1176 | - text_area(object_name, method, { :id => text_area_id, :onkeyup => "grow_text_area('#{text_area_id}')" }.merge(options)) | |
1209 | + options[:class] = (options[:class] || '') + ' autogrow' | |
1210 | + text_area(object_name, method, { :id => text_area_id }.merge(options)) | |
1177 | 1211 | end |
1178 | 1212 | |
1179 | 1213 | def pluralize_without_count(count, singular, plural = nil) |
... | ... | @@ -1184,35 +1218,6 @@ module ApplicationHelper |
1184 | 1218 | list.sort.inject(Hash.new(0)){|h,i| h[i] += 1; h }.collect{ |x, n| [n, connector, x].join(" ") }.sort |
1185 | 1219 | end |
1186 | 1220 | |
1187 | - #FIXME Use time_ago_in_words instead of this method if you're using Rails 2.2+ | |
1188 | - def time_ago_as_sentence(from_time, include_seconds = false) | |
1189 | - to_time = Time.now | |
1190 | - from_time = Time.parse(from_time.to_s) | |
1191 | - from_time = from_time.to_time if from_time.respond_to?(:to_time) | |
1192 | - to_time = to_time.to_time if to_time.respond_to?(:to_time) | |
1193 | - distance_in_minutes = (((to_time - from_time).abs)/60).round | |
1194 | - distance_in_seconds = ((to_time - from_time).abs).round | |
1195 | - case distance_in_minutes | |
1196 | - when 0..1 | |
1197 | - return (distance_in_minutes == 0) ? _('less than a minute') : _('1 minute') unless include_seconds | |
1198 | - case distance_in_seconds | |
1199 | - when 0..4 then _('less than 5 seconds') | |
1200 | - when 5..9 then _('less than 10 seconds') | |
1201 | - when 10..19 then _('less than 20 seconds') | |
1202 | - when 20..39 then _('half a minute') | |
1203 | - when 40..59 then _('less than a minute') | |
1204 | - else _('1 minute') | |
1205 | - end | |
1206 | - | |
1207 | - when 2..44 then _('%{distance} minutes ago') % { :distance => distance_in_minutes } | |
1208 | - when 45..89 then _('about 1 hour ago') | |
1209 | - when 90..1439 then _('about %{distance} hours ago') % { :distance => (distance_in_minutes.to_f / 60.0).round } | |
1210 | - when 1440..2879 then _('1 day ago') | |
1211 | - when 2880..10079 then _('%{distance} days ago') % { :distance => (distance_in_minutes / 1440).round } | |
1212 | - else show_time(from_time) | |
1213 | - end | |
1214 | - end | |
1215 | - | |
1216 | 1221 | def comment_balloon(options = {}, &block) |
1217 | 1222 | wrapper = content_tag(:div, capture(&block), :class => 'comment-balloon-content') |
1218 | 1223 | (1..8).to_a.reverse.each { |i| wrapper = content_tag(:div, wrapper, :class => "comment-wrapper-#{i}") } |
... | ... | @@ -1231,7 +1236,7 @@ module ApplicationHelper |
1231 | 1236 | |
1232 | 1237 | def task_information(task) |
1233 | 1238 | values = {} |
1234 | - values.merge!({:requestor => link_to(task.requestor.name, task.requestor.public_profile_url)}) if task.requestor | |
1239 | + values.merge!({:requestor => link_to(task.requestor.name, task.requestor.url)}) if task.requestor | |
1235 | 1240 | values.merge!({:subject => content_tag('span', task.subject, :class=>'task_target')}) if task.subject |
1236 | 1241 | values.merge!({:linked_subject => link_to(content_tag('span', task.linked_subject[:text], :class => 'task_target'), task.linked_subject[:url])}) if task.linked_subject |
1237 | 1242 | values.merge!(task.information[:variables]) if task.information[:variables] |
... | ... | @@ -1336,18 +1341,29 @@ module ApplicationHelper |
1336 | 1341 | def template_options(kind, field_name) |
1337 | 1342 | templates = environment.send(kind).templates |
1338 | 1343 | return '' if templates.count == 0 |
1339 | - return hidden_field_tag("#{field_name}[template_id]", templates.first.id) if templates.count == 1 | |
1340 | - | |
1341 | - radios = templates.map do |template| | |
1342 | - content_tag('li', labelled_radio_button(link_to(template.name, template.url, :target => '_blank'), "#{field_name}[template_id]", template.id, environment.is_default_template?(template))) | |
1343 | - end.join("\n") | |
1344 | - | |
1345 | - content_tag('div', content_tag('label', _('Profile organization'), :for => 'template-options', :class => 'formlabel') + | |
1346 | - content_tag('p', _('Your profile will be created according to the selected template. Click on the options to view them.'), :style => 'margin: 5px 15px;padding: 0px 10px;') + | |
1347 | - content_tag('ul', radios, :style => 'list-style: none; padding-left: 20px; margin-top: 0.5em;'), | |
1348 | - :id => 'template-options', | |
1349 | - :style => 'margin-top: 1em' | |
1350 | - ) | |
1344 | + if templates.count == 1 | |
1345 | + if templates.first.custom_fields == {} | |
1346 | + return hidden_field_tag("#{field_name}[template_id]", templates.first.id) | |
1347 | + else | |
1348 | + custom_fields = "" | |
1349 | + templates.first.custom_fields.each { |field, value| | |
1350 | + custom_fields += content_tag('div', content_tag('label', value[:title].capitalize, :class => 'formlabel') + | |
1351 | + content_tag('div', text_field_tag( "profile_data[custom_fields][#{field}][title]", ''), :class => 'formfield type-text'), :class => "formfieldline" ) if value[:signup] == 'on' | |
1352 | + } | |
1353 | + content_tag('div', custom_fields) | |
1354 | + end | |
1355 | + else | |
1356 | + radios = templates.map do |template| | |
1357 | + content_tag('li', labelled_radio_button(link_to(template.name, template.url, :target => '_blank'), "#{field_name}[template_id]", template.id, environment.is_default_template?(template), :onchange => 'show_fields_for_template(this);')) | |
1358 | + end.join("\n") | |
1359 | + | |
1360 | + content_tag('div', content_tag('label', _('Profile organization'), :for => 'template-options', :class => 'formlabel') + | |
1361 | + content_tag('p', _('Your profile will be created according to the selected template. Click on the options to view them.'), :style => 'margin: 5px 15px;padding: 0px 10px;') + | |
1362 | + content_tag('ul', radios, :style => 'list-style: none; padding-left: 20px; margin-top: 0.5em;'), | |
1363 | + :id => 'template-options', | |
1364 | + :style => 'margin-top: 1em' | |
1365 | + ) | |
1366 | + end | |
1351 | 1367 | end |
1352 | 1368 | |
1353 | 1369 | def expirable_content_reference(content, action, text, url, options = {}) |
... | ... | @@ -1480,4 +1496,26 @@ module ApplicationHelper |
1480 | 1496 | text_field(object_name, method, options.merge(:class => 'colorpicker_field')) |
1481 | 1497 | end |
1482 | 1498 | |
1499 | + def fullscreen_buttons(itemId) | |
1500 | + content=" | |
1501 | + <script>fullscreenPageLoad('#{itemId}')</script> | |
1502 | + " | |
1503 | + content+=content_tag('a', content_tag('span',_("Full screen")), | |
1504 | + { :id=>"fullscreen-btn", | |
1505 | + :onClick=>"toggle_fullwidth('#{itemId}')", | |
1506 | + :class=>"button with-text icon-fullscreen", | |
1507 | + :href=>"#", | |
1508 | + :title=>_("Go to full screen mode") | |
1509 | + }) | |
1510 | + | |
1511 | + content+=content_tag('a', content_tag('span',_("Exit full screen")), | |
1512 | + { :style=>"display: none;", | |
1513 | + :id=>"exit-fullscreen-btn", | |
1514 | + :onClick=>"toggle_fullwidth('#{itemId}')", | |
1515 | + :class=>"button with-text icon-fullscreen", | |
1516 | + :href=>"#", | |
1517 | + :title=>_("Exit full screen mode") | |
1518 | + }) | |
1519 | + end | |
1520 | + | |
1483 | 1521 | end | ... | ... |
app/helpers/article_helper.rb
... | ... | @@ -12,6 +12,7 @@ module ArticleHelper |
12 | 12 | @article = article |
13 | 13 | |
14 | 14 | visibility_options(@article, tokenized_children) + |
15 | + topic_creation(@article) + | |
15 | 16 | content_tag('h4', _('Options')) + |
16 | 17 | content_tag('div', |
17 | 18 | (article.profile.has_members? ? |
... | ... | @@ -55,14 +56,7 @@ module ArticleHelper |
55 | 56 | 'div', |
56 | 57 | check_box(:article, :display_versions) + |
57 | 58 | content_tag('label', _('I want this article to display a link to older versions'), :for => 'article_display_versions') |
58 | - ) : '') + | |
59 | - | |
60 | - (article.forum? && article.profile.community? ? | |
61 | - content_tag( | |
62 | - 'div', | |
63 | - check_box(:article, :allows_members_to_create_topics) + | |
64 | - content_tag('label', _('Allow members to create topics'), :for => 'article_allows_members_to_create_topics') | |
65 | - ) : '') | |
59 | + ) : '') | |
66 | 60 | ) |
67 | 61 | end |
68 | 62 | |
... | ... | @@ -81,6 +75,22 @@ module ArticleHelper |
81 | 75 | ) |
82 | 76 | end |
83 | 77 | |
78 | + def topic_creation(article) | |
79 | + return '' unless article.forum? | |
80 | + | |
81 | + general_options = Forum::TopicCreation.general_options(article) | |
82 | + slider_options = {:id => 'topic-creation-slider'} | |
83 | + slider_options = general_options.keys.inject(slider_options) do |result, option| | |
84 | + result.merge!({'data-'+option => general_options[option]}) | |
85 | + end | |
86 | + | |
87 | + content_tag('h4', _('Topic creation')) + | |
88 | + content_tag( 'small', _('Who will be able to create new topics on this forum?')) + | |
89 | + content_tag('div', '', slider_options) + | |
90 | + hidden_field_tag('article[topic_creation]', article.topic_creation) + | |
91 | + javascript_include_tag('topic-creation-config') | |
92 | + end | |
93 | + | |
84 | 94 | def privacity_exceptions(article, tokenized_children) |
85 | 95 | content_tag('div', |
86 | 96 | content_tag('div', | ... | ... |
app/helpers/blog_helper.rb
... | ... | @@ -22,7 +22,9 @@ module BlogHelper |
22 | 22 | :param_name => 'npage', |
23 | 23 | :previous_label => _('« Newer posts'), |
24 | 24 | :next_label => _('Older posts »'), |
25 | - :params => {:action=>"view_page", :page=>articles.first.parent.path.split('/'), :controller=>"content_viewer"} | |
25 | + :params => {:action=>"view_page", | |
26 | + :page=>articles.first.parent.path.split('/'), | |
27 | + :controller=>"content_viewer"} | |
26 | 28 | }) if articles.present? && conf[:paginate] |
27 | 29 | content = [] |
28 | 30 | artic_len = articles.length |
... | ... | @@ -44,7 +46,7 @@ module BlogHelper |
44 | 46 | end |
45 | 47 | |
46 | 48 | def display_post(article, format = 'full') |
47 | - no_comments = (format == 'full') ? false : true | |
49 | + no_comments = (format == 'full' || format == 'compact' ) ? false : true | |
48 | 50 | title = article_title(article, :no_comments => no_comments) |
49 | 51 | method = "display_#{format.split('+')[0]}_format" |
50 | 52 | html = send(method, FilePresenter.for(article)).html_safe |
... | ... | @@ -55,8 +57,12 @@ module BlogHelper |
55 | 57 | else |
56 | 58 | '<div class="post-pic" style="background-image:url('+img+')"></div>' |
57 | 59 | end |
58 | - end.to_s + | |
59 | - title + html | |
60 | + end.to_s + title + html | |
61 | + end | |
62 | + | |
63 | + def display_compact_format(article) | |
64 | + render :file => 'content_viewer/_display_compact_format', | |
65 | + :locals => { :article => article, :format => "compact" } | |
60 | 66 | end |
61 | 67 | |
62 | 68 | def display_full_format(article) | ... | ... |
app/helpers/box_organizer_helper.rb
1 | 1 | module BoxOrganizerHelper |
2 | 2 | |
3 | + def display_icon(block) | |
4 | + image_path = nil | |
5 | + plugin = @plugins.fetch_first_plugin(:has_block?, block) | |
6 | + | |
7 | + theme = Theme.new(environment.theme) # remove this | |
8 | + if File.exists?(File.join(theme.filesystem_path, 'images', block.icon_path)) | |
9 | + image_path = File.join(theme.public_path, 'images', block.icon_path) | |
10 | + elsif plugin && File.exists?(File.join(Rails.root, 'public', plugin.public_path, 'images', block.icon_path)) | |
11 | + image_path = File.join('/', plugin.public_path, 'images', block.icon_path) | |
12 | + elsif File.exists?(File.join(Rails.root, 'public', 'images', block.icon_path)) | |
13 | + image_path = File.join('images', block.icon_path) | |
14 | + else | |
15 | + image_path = File.join('images', block.default_icon_path) | |
16 | + end | |
17 | + | |
18 | + image_tag(image_path, height: '48', width: '48', class: 'block-type-icon', alt: '' ) | |
19 | + end | |
20 | + | |
21 | + def display_previews(block) | |
22 | + images_path = nil | |
23 | + plugin = @plugins.fetch_first_plugin(:has_block?, block) | |
24 | + | |
25 | + theme = Theme.new(environment.theme) # remove this | |
26 | + | |
27 | + images_path = Dir.glob(File.join(theme.filesystem_path, 'images', block.preview_path, '*')) | |
28 | + images_path = images_path.map{|path| path.gsub(theme.filesystem_path, theme.public_path) } unless images_path.empty? | |
29 | + | |
30 | + images_path = Dir.glob(File.join(Rails.root, 'public', plugin.public_path, 'images', block.preview_path, '*')) if plugin && images_path.empty? | |
31 | + images_path = images_path.map{|path| path.gsub(File.join(Rails.root, 'public'), '') } unless images_path.empty? | |
32 | + | |
33 | + images_path = Dir.glob(File.join(Rails.root, 'public', 'images', block.preview_path, '*')) if images_path.empty? | |
34 | + images_path = images_path.map{|path| path.gsub(File.join(Rails.root, 'public'), '') } unless images_path.empty? | |
35 | + | |
36 | + images_path = 1.upto(3).map{File.join('images', block.default_preview_path)} if images_path.empty? | |
37 | + | |
38 | + content_tag(:ul, | |
39 | + images_path.map do |preview| | |
40 | + content_tag(:li, image_tag(preview, height: '240', alt: '')) | |
41 | + end.join("\n") | |
42 | + ) | |
43 | + end | |
44 | + | |
3 | 45 | def icon_selector(icon = 'no-ico') |
4 | 46 | render :partial => 'icon_selector', :locals => { :icon => icon } |
5 | 47 | end |
... | ... | @@ -10,4 +52,4 @@ module BoxOrganizerHelper |
10 | 52 | end |
11 | 53 | end |
12 | 54 | |
13 | -end | |
14 | 55 | \ No newline at end of file |
56 | +end | ... | ... |
app/helpers/boxes_helper.rb
... | ... | @@ -122,7 +122,7 @@ module BoxesHelper |
122 | 122 | end |
123 | 123 | |
124 | 124 | def wrap_main_content(content) |
125 | - (1..8).to_a.reverse.inject(content) { |acc,n| content_tag('div', acc, :id => 'main-content-wrapper-' + n.to_s) } | |
125 | + content_tag('div', content, :class => 'main-content') | |
126 | 126 | end |
127 | 127 | |
128 | 128 | def extract_block_content(content) |
... | ... | @@ -190,8 +190,9 @@ module BoxesHelper |
190 | 190 | else |
191 | 191 | "before-block-#{block.id}" |
192 | 192 | end |
193 | - if block.nil? or modifiable?(block) | |
194 | - content_tag('div', ' ', :id => id, :class => 'block-target' ) + drop_receiving_element(id, :url => { :action => 'move_block', :target => id }, :accept => box.acceptable_blocks, :hoverclass => 'block-target-hover') | |
193 | + if block.nil? || movable?(block) | |
194 | + url = url_for(:action => 'move_block', :target => id) | |
195 | + content_tag('div', _('Drop Here'), :id => id, :class => 'block-target' ) + drop_receiving_element(id, :accept => box.acceptable_blocks, :hoverclass => 'block-target-hover', :activeClass => 'block-target-active', :tolerance => 'pointer', :onDrop => "function(ev, ui) { dropBlock('#{url}', '#{_('loading...')}', ev, ui);}") | |
195 | 196 | else |
196 | 197 | "" |
197 | 198 | end |
... | ... | @@ -199,14 +200,32 @@ module BoxesHelper |
199 | 200 | |
200 | 201 | # makes the given block draggable so it can be moved away. |
201 | 202 | def block_handle(block) |
202 | - modifiable?(block) ? draggable_element("block-#{block.id}", :revert => true) : "" | |
203 | + return "" unless movable?(block) | |
204 | + icon = "<div><div>#{display_icon(block.class)}</div><span>#{_(block.class.pretty_name)}</span></div>" | |
205 | + block_draggable("block-#{block.id}", | |
206 | + :helper => "function() {return cloneDraggableBlock($(this), '#{icon}')}") | |
207 | + end | |
208 | + | |
209 | + def block_draggable(element_id, options={}) | |
210 | + draggable_options = { | |
211 | + :revert => "'invalid'", | |
212 | + :appendTo => "'#block-store-draggables'", | |
213 | + :helper => '"clone"', | |
214 | + :revertDuration => 200, | |
215 | + :scroll => false, | |
216 | + :start => "startDragBlock", | |
217 | + :stop => "stopDragBlock", | |
218 | + :cursor => "'move'", | |
219 | + :cursorAt => '{ left: 0, top:0, right:0, bottom:0 }', | |
220 | + }.merge(options) | |
221 | + draggable_element(element_id, draggable_options) | |
203 | 222 | end |
204 | 223 | |
205 | 224 | def block_edit_buttons(block) |
206 | 225 | buttons = [] |
207 | 226 | nowhere = 'javascript: return false;' |
208 | 227 | |
209 | - if modifiable?(block) | |
228 | + if movable?(block) | |
210 | 229 | if block.first? |
211 | 230 | buttons << icon_button('up-disabled', _("Can't move up anymore."), nowhere) |
212 | 231 | else |
... | ... | @@ -229,15 +248,15 @@ module BoxesHelper |
229 | 248 | buttons << icon_button('left', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[1].id.to_s, :id => block.id }, :method => 'post' ) |
230 | 249 | end |
231 | 250 | end |
251 | + end | |
232 | 252 | |
233 | - if block.editable? | |
234 | - buttons << modal_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id }) | |
235 | - end | |
253 | + if editable?(block) | |
254 | + buttons << modal_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id }) | |
255 | + end | |
236 | 256 | |
237 | - if !block.main? | |
238 | - buttons << icon_button(:delete, _('Remove block'), { :action => 'remove', :id => block.id }, { :method => 'post', :confirm => _('Are you sure you want to remove this block?')}) | |
239 | - buttons << icon_button(:clone, _('Clone'), { :action => 'clone_block', :id => block.id }, { :method => 'post' }) | |
240 | - end | |
257 | + if movable?(block) && !block.main? | |
258 | + buttons << icon_button(:delete, _('Remove block'), { :action => 'remove', :id => block.id }, { :method => 'post', :confirm => _('Are you sure you want to remove this block?')}) | |
259 | + buttons << icon_button(:clone, _('Clone'), { :action => 'clone_block', :id => block.id }, { :method => 'post' }) | |
241 | 260 | end |
242 | 261 | |
243 | 262 | if block.respond_to?(:help) |
... | ... | @@ -273,7 +292,11 @@ module BoxesHelper |
273 | 292 | classes |
274 | 293 | end |
275 | 294 | |
276 | - def modifiable?(block) | |
277 | - return !block.fixed || environment.admins.include?(user) | |
295 | + def movable?(block) | |
296 | + return block.movable? || user.is_admin? | |
297 | + end | |
298 | + | |
299 | + def editable?(block) | |
300 | + return block.editable? || user.is_admin? | |
278 | 301 | end |
279 | 302 | end | ... | ... |
app/helpers/chat_helper.rb
... | ... | @@ -9,12 +9,12 @@ module ChatHelper |
9 | 9 | avatar = profile_image(user, :portrait, :class => 'avatar') |
10 | 10 | content_tag('span', |
11 | 11 | link_to(avatar + content_tag('span', user.name) + ui_icon('ui-icon-triangle-1-s'), |
12 | - '#', | |
12 | + '', | |
13 | 13 | :onclick => 'toggleMenu(this); return false', |
14 | 14 | :class => icon_class + ' simplemenu-trigger' |
15 | 15 | ) + |
16 | 16 | content_tag('ul', |
17 | - links.map{|link| content_tag('li', link_to(link[1], '#', :class => link[0], :id => link[2], 'data-jid' => user.jid), :class => 'simplemenu-item') }.join("\n"), | |
17 | + links.map{|link| content_tag('li', link_to(link[1], '', :class => link[0], :id => link[2], 'data-jid' => user.jid), :class => 'simplemenu-item') }.join("\n"), | |
18 | 18 | :style => 'display: none; z-index: 100', |
19 | 19 | :class => 'simplemenu-submenu' |
20 | 20 | ), | ... | ... |
app/helpers/comment_helper.rb
1 | 1 | module CommentHelper |
2 | + include DatesHelper | |
2 | 3 | |
3 | 4 | def article_title(article, args = {}) |
4 | 5 | title = article.title |
... | ... | @@ -15,7 +16,7 @@ module CommentHelper |
15 | 16 | content_tag('span', show_date(article.published_at), :class => 'date') + |
16 | 17 | content_tag('span', [_(", by %s") % link_to(article.author_name, article.author_url)], :class => 'author') + |
17 | 18 | content_tag('span', comments, :class => 'comments'), |
18 | - :class => 'created-at' | |
19 | + :class => 'publishing-info' | |
19 | 20 | ) |
20 | 21 | end |
21 | 22 | title | ... | ... |
app/helpers/content_viewer_helper.rb
... | ... | @@ -2,6 +2,7 @@ module ContentViewerHelper |
2 | 2 | |
3 | 3 | include BlogHelper |
4 | 4 | include ForumHelper |
5 | + include DatesHelper | |
5 | 6 | |
6 | 7 | def display_number_of_comments(n) |
7 | 8 | base_str = "<span class='comment-count hide'>#{n}</span>" |
... | ... | @@ -24,16 +25,35 @@ module ContentViewerHelper |
24 | 25 | unless args[:no_comments] || !article.accept_comments |
25 | 26 | comments = (" - %s") % link_to_comments(article) |
26 | 27 | end |
28 | + date_format = show_with_right_format_date article | |
27 | 29 | title << content_tag('span', |
28 | - content_tag('span', show_date(article.published_at), :class => 'date') + | |
30 | + date_format + | |
29 | 31 | content_tag('span', _(", by %s") % (article.author ? link_to(article.author_name, article.author_url) : article.author_name), :class => 'author') + |
30 | 32 | content_tag('span', comments, :class => 'comments'), |
31 | - :class => 'created-at' | |
33 | + :class => 'publishing-info' | |
32 | 34 | ) |
33 | 35 | end |
34 | 36 | title |
35 | 37 | end |
36 | 38 | |
39 | + def show_with_right_format_date article | |
40 | + date_format = article.environment.date_format | |
41 | + use_numbers = false | |
42 | + year = true | |
43 | + left_time = false | |
44 | + if date_format == 'numbers_with_year' | |
45 | + use_numbers = true | |
46 | + elsif date_format == 'numbers' | |
47 | + use_numbers = true | |
48 | + year = false | |
49 | + elsif date_format == 'month_name' | |
50 | + year = false | |
51 | + elsif date_format == 'past_time' | |
52 | + left_time = true | |
53 | + end | |
54 | + content_tag('span', show_time(article.published_at, use_numbers , year, left_time), :class => 'date') | |
55 | + end | |
56 | + | |
37 | 57 | def link_to_comments(article, args = {}) |
38 | 58 | return '' unless article.accept_comments? |
39 | 59 | reference_to_article number_of_comments(article), article, 'comments_list' | ... | ... |
app/helpers/dates_helper.rb
... | ... | @@ -2,6 +2,7 @@ require 'noosfero/i18n' |
2 | 2 | |
3 | 3 | module DatesHelper |
4 | 4 | |
5 | + include ActionView::Helpers::DateHelper | |
5 | 6 | def months |
6 | 7 | I18n.t('date.month_names') |
7 | 8 | end |
... | ... | @@ -15,10 +16,12 @@ module DatesHelper |
15 | 16 | end |
16 | 17 | |
17 | 18 | # formats a date for displaying. |
18 | - def show_date(date, use_numbers = false, year=true) | |
19 | + def show_date(date, use_numbers = false, year = true, left_time = false) | |
19 | 20 | if date && use_numbers |
20 | 21 | date_format = year ? _('%{month}/%{day}/%{year}') : _('%{month}/%{day}') |
21 | 22 | date_format % { :day => date.day, :month => date.month, :year => date.year } |
23 | + elsif date && left_time | |
24 | + date_format = time_ago_in_words(date) | |
22 | 25 | elsif date |
23 | 26 | date_format = year ? _('%{month_name} %{day}, %{year}') : _('%{month_name} %{day}') |
24 | 27 | date_format % { :day => date.day, :month_name => month_name(date.month), :year => date.year } |
... | ... | @@ -40,9 +43,14 @@ module DatesHelper |
40 | 43 | end |
41 | 44 | |
42 | 45 | # formats a datetime for displaying. |
43 | - def show_time(time) | |
44 | - if time | |
45 | - _('%{day} %{month} %{year}, %{hour}:%{minutes}') % { :year => time.year, :month => month_name(time.month), :day => time.day, :hour => time.hour, :minutes => time.strftime("%M") } | |
46 | + def show_time(time, use_numbers = false, year = true, left_time = false) | |
47 | + if time && use_numbers | |
48 | + _('%{month}/%{day}/%{year}, %{hour}:%{minutes}') % { :year => (year ? time.year : ''), :month => time.month, :day => time.day, :hour => time.hour, :minutes => time.strftime("%M") } | |
49 | + elsif time && left_time | |
50 | + date_format = time_ago_in_words(time) | |
51 | + elsif time | |
52 | + date_format = year ? _('%{month_name} %{day}, %{year} %{hour}:%{minutes}') : _('%{month_name} %{day} %{hour}:%{minutes}') | |
53 | + date_format % { :day => time.day, :month_name => month_name(time.month), :year => time.year, :hour => time.hour, :minutes => time.strftime("%M") } | |
46 | 54 | else |
47 | 55 | '' |
48 | 56 | end |
... | ... | @@ -50,7 +58,7 @@ module DatesHelper |
50 | 58 | |
51 | 59 | def show_period(date1, date2 = nil, use_numbers = false) |
52 | 60 | if (date1 == date2) || (date2.nil?) |
53 | - show_date(date1, use_numbers) | |
61 | + show_time(date1, use_numbers) | |
54 | 62 | else |
55 | 63 | if date1.year == date2.year |
56 | 64 | if date1.month == date2.month |
... | ... | @@ -69,8 +77,8 @@ module DatesHelper |
69 | 77 | end |
70 | 78 | else |
71 | 79 | _('from %{date1} to %{date2}') % { |
72 | - :date1 => show_date(date1, use_numbers), | |
73 | - :date2 => show_date(date2, use_numbers) | |
80 | + :date1 => show_time(date1, use_numbers), | |
81 | + :date2 => show_time(date2, use_numbers) | |
74 | 82 | } |
75 | 83 | end |
76 | 84 | end |
... | ... | @@ -103,18 +111,18 @@ module DatesHelper |
103 | 111 | |
104 | 112 | def build_date(year, month, day = 1) |
105 | 113 | if year.blank? and month.blank? and day.blank? |
106 | - Date.today | |
114 | + DateTime.now | |
107 | 115 | else |
108 | 116 | if year.blank? |
109 | - year = Date.today.year | |
117 | + year = DateTime.now.year | |
110 | 118 | end |
111 | 119 | if month.blank? |
112 | - month = Date.today.month | |
120 | + month = DateTime.now.month | |
113 | 121 | end |
114 | 122 | if day.blank? |
115 | 123 | day = 1 |
116 | 124 | end |
117 | - Date.new(year.to_i, month.to_i, day.to_i) | |
125 | + DateTime.new(year.to_i, month.to_i, day.to_i) | |
118 | 126 | end |
119 | 127 | end |
120 | 128 | ... | ... |
... | ... | @@ -0,0 +1,12 @@ |
1 | +module EmailTemplateHelper | |
2 | + | |
3 | + def mail_with_template(params={}) | |
4 | + if params[:email_template].present? | |
5 | + params[:body] = params[:email_template].parsed_body(params[:template_params]) | |
6 | + params[:subject] = params[:email_template].parsed_subject(params[:template_params]) | |
7 | + params[:content_type] = "text/html" | |
8 | + end | |
9 | + mail(params.except(:email_template)) | |
10 | + end | |
11 | + | |
12 | +end | ... | ... |
app/helpers/events_helper.rb
1 | 1 | module EventsHelper |
2 | 2 | |
3 | + include DatesHelper | |
3 | 4 | def list_events(date, events) |
4 | 5 | title = _('Events for %s') % show_date_month(date) |
5 | 6 | content_tag('h2', title) + |
... | ... | @@ -15,7 +16,7 @@ module EventsHelper |
15 | 16 | |
16 | 17 | content_tag( 'tr', |
17 | 18 | content_tag('td', |
18 | - content_tag('div', show_date(article.start_date) + ( article.end_date.nil? ? '' : (_(" to ") + show_date(article.end_date))),:class => 'event-date' ) + | |
19 | + content_tag('div', show_time(article.start_date) + ( article.end_date.nil? ? '' : (_(" to ") + show_time(article.end_date))),:class => 'event-date' ) + | |
19 | 20 | content_tag('div',link_to(article.name,article.url),:class => 'event-title') + |
20 | 21 | content_tag('div',(article.address.nil? or article.address == '') ? '' : (_('Place: ') + article.address),:class => 'event-place') |
21 | 22 | ) |
... | ... | @@ -29,7 +30,7 @@ module EventsHelper |
29 | 30 | # the day itself |
30 | 31 | date, |
31 | 32 | # is there any events in this date? |
32 | - events.any? {|event| event.date_range.include?(date)}, | |
33 | + events.any? {|event| event.date_range.cover?(date)}, | |
33 | 34 | # is this date in the current month? |
34 | 35 | true |
35 | 36 | ] | ... | ... |
app/helpers/folder_helper.rb
1 | -require 'short_filename' | |
2 | - | |
3 | 1 | module FolderHelper |
4 | 2 | |
5 | - include ShortFilename | |
6 | 3 | include ArticleHelper |
7 | 4 | |
8 | 5 | def list_contents(configure={}) |
... | ... | @@ -10,8 +7,8 @@ module FolderHelper |
10 | 7 | configure[:list_type] ||= :folder |
11 | 8 | if !configure[:contents].blank? |
12 | 9 | configure[:contents] = configure[:contents].paginate( |
13 | - :order => "updated_at DESC", | |
14 | - :per_page => 10, | |
10 | + :order => "name ASC", | |
11 | + :per_page => 30, | |
15 | 12 | :page => params[:npage] |
16 | 13 | ) |
17 | 14 | |
... | ... | @@ -25,49 +22,32 @@ module FolderHelper |
25 | 22 | articles.select {|article| article.display_to?(user)} |
26 | 23 | end |
27 | 24 | |
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] | |
25 | + def display_content_icon(content_item) | |
26 | + content = FilePresenter.for content_item | |
33 | 27 | content_link = if content.image? |
34 | - link_to(' ' * (level * 4) + | |
35 | - image_tag(icon_for_article(content)) + short_filename(content.name), | |
28 | + link_to( | |
29 | + image_tag(icon_for_article(content, :bigicon)), | |
36 | 30 | content.url.merge(:view => true) |
37 | 31 | ) |
38 | 32 | else |
39 | - link_to(' ' * (level * 4) + | |
40 | - short_filename(content.name), | |
41 | - content.url.merge(:view => true), :class => icon_for_article(content) | |
33 | + link_to('', | |
34 | + content.url.merge(:view => true), | |
35 | + :class => icon_for_article(content, :bigicon) | |
42 | 36 | ) |
43 | 37 | end |
44 | - result = content_tag( | |
45 | - 'tr', | |
46 | - content_tag('td', content_link ) + | |
47 | - content_tag('td', show_date(content.updated_at), :class => 'last-update'), | |
48 | - :class => "#{list_type}-item" | |
49 | - ) | |
50 | - if recursive | |
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") | |
55 | - else | |
56 | - result | |
57 | - end | |
58 | 38 | end |
59 | 39 | |
60 | - def icon_for_article(article) | |
40 | + def icon_for_article(article, size = 'icon') | |
61 | 41 | article = FilePresenter.for article |
62 | - icon = article.respond_to?(:icon_name) ? | |
63 | - article.icon_name : | |
64 | - article.class.icon_name(article) | |
65 | - if (icon =~ /\//) | |
66 | - icon | |
42 | + if article.respond_to?(:sized_icon) | |
43 | + article.sized_icon(size) | |
67 | 44 | else |
68 | - klasses = 'icon ' + [icon].flatten.map{|name| 'icon-'+name}.join(' ') | |
45 | + icon = article.respond_to?(:icon_name) ? | |
46 | + article.icon_name : | |
47 | + article.class.icon_name(article) | |
48 | + klasses = "#{size} " + [icon].flatten.map{|name| "#{size}-"+name}.join(' ') | |
69 | 49 | if article.kind_of?(UploadedFile) || article.kind_of?(FilePresenter) |
70 | - klasses += ' icon-upload-file' | |
50 | + klasses += " #{size}-upload-file" | |
71 | 51 | end |
72 | 52 | klasses |
73 | 53 | end | ... | ... |
app/helpers/forms_helper.rb
... | ... | @@ -151,7 +151,7 @@ module FormsHelper |
151 | 151 | datepicker_options[:close_text] ||= _('Done') |
152 | 152 | datepicker_options[:constrain_input] ||= true |
153 | 153 | datepicker_options[:current_text] ||= _('Today') |
154 | - datepicker_options[:date_format] ||= 'mm/dd/yy' | |
154 | + datepicker_options[:date_format] ||= 'yy/mm/dd' | |
155 | 155 | datepicker_options[:day_names] ||= [_('Sunday'), _('Monday'), _('Tuesday'), _('Wednesday'), _('Thursday'), _('Friday'), _('Saturday')] |
156 | 156 | datepicker_options[:day_names_min] ||= [_('Su'), _('Mo'), _('Tu'), _('We'), _('Th'), _('Fr'), _('Sa')] |
157 | 157 | datepicker_options[:day_names_short] ||= [_('Sun'), _('Mon'), _('Tue'), _('Wed'), _('Thu'), _('Fri'), _('Sat')] |
... | ... | @@ -236,7 +236,7 @@ module FormsHelper |
236 | 236 | weekHeader: #{datepicker_options[:week_header].to_json}, |
237 | 237 | yearRange: #{datepicker_options[:year_range].to_json}, |
238 | 238 | yearSuffix: #{datepicker_options[:year_suffix].to_json} |
239 | - }) | |
239 | + }).datepicker('setDate', new Date('#{value}')) | |
240 | 240 | </script> |
241 | 241 | ".html_safe |
242 | 242 | result | ... | ... |
app/helpers/forum_helper.rb
1 | 1 | module ForumHelper |
2 | + include ActionView::Helpers::DateHelper | |
2 | 3 | |
3 | 4 | def cms_label_for_new_children |
4 | 5 | _('New discussion topic') |
... | ... | @@ -42,9 +43,9 @@ module ForumHelper |
42 | 43 | def last_topic_update(article) |
43 | 44 | info = article.info_from_last_update |
44 | 45 | if info[:author_url] |
45 | - time_ago_as_sentence(info[:date]) + ' ' + _('by') + ' ' + link_to(info[:author_name], info[:author_url]) | |
46 | + time_ago_in_words(info[:date]) + ' ' + _('by') + ' ' + link_to(info[:author_name], info[:author_url]) | |
46 | 47 | else |
47 | - time_ago_as_sentence(info[:date]) + ' ' + _('by') + ' ' + info[:author_name] | |
48 | + time_ago_in_words(info[:date]) + ' ' + _('by') + ' ' + info[:author_name] | |
48 | 49 | end |
49 | 50 | end |
50 | 51 | ... | ... |
app/helpers/layout_helper.rb
... | ... | @@ -28,7 +28,7 @@ module LayoutHelper |
28 | 28 | end |
29 | 29 | |
30 | 30 | def noosfero_javascript |
31 | - plugins_javascripts = @plugins.flat_map{ |plugin| plugin.js_files.map{ |js| plugin.class.public_path(js, true) } }.flatten | |
31 | + plugins_javascripts = @plugins.flat_map{ |plugin| Array.wrap(plugin.js_files).map{ |js| plugin.class.public_path(js, true) } }.flatten | |
32 | 32 | |
33 | 33 | output = '' |
34 | 34 | output += render 'layouts/javascript' |
... | ... | @@ -38,6 +38,8 @@ module LayoutHelper |
38 | 38 | output += theme_javascript_ng.to_s |
39 | 39 | output += javascript_tag 'render_all_jquery_ui_widgets()' |
40 | 40 | |
41 | + output += templete_javascript_ng.to_s | |
42 | + | |
41 | 43 | output |
42 | 44 | end |
43 | 45 | |
... | ... | @@ -70,24 +72,13 @@ module LayoutHelper |
70 | 72 | end |
71 | 73 | |
72 | 74 | def template_stylesheet_path |
73 | - if profile.nil? | |
74 | - "/designs/templates/#{environment.layout_template}/stylesheets/style.css" | |
75 | - else | |
76 | - "/designs/templates/#{profile.layout_template}/stylesheets/style.css" | |
77 | - end | |
75 | + File.join template_path, "/stylesheets/style.css" | |
78 | 76 | end |
79 | 77 | |
80 | 78 | |
81 | 79 | def icon_theme_stylesheet_path |
82 | - icon_themes = [] | |
83 | 80 | theme_icon_themes = theme_option(:icon_theme) || [] |
84 | - for icon_theme in theme_icon_themes do | |
85 | - theme_path = "designs/icons/#{icon_theme}/style.css" | |
86 | - if File.exists?(Rails.root.join('public', theme_path)) | |
87 | - icon_themes << theme_path | |
88 | - end | |
89 | - end | |
90 | - icon_themes | |
81 | + theme_icon_themes.map{ |it| "designs/icons/#{it}/style.css" } | |
91 | 82 | end |
92 | 83 | |
93 | 84 | def jquery_ui_theme_stylesheet_path | ... | ... |
app/helpers/manage_products_helper.rb
... | ... | @@ -75,9 +75,12 @@ module ManageProductsHelper |
75 | 75 | end |
76 | 76 | |
77 | 77 | def categories_container(categories_selection_html, hierarchy_html = '') |
78 | - hidden_field_tag('selected_category_id') + | |
79 | - content_tag('div', hierarchy_html, :id => 'hierarchy_navigation') + | |
80 | - content_tag('div', categories_selection_html, :id => 'categories_container_wrapper') | |
78 | + content_tag 'div', | |
79 | + render('categories_autocomplete') + | |
80 | + hidden_field_tag('selected_category_id') + | |
81 | + content_tag('div', hierarchy_html, :id => 'hierarchy_navigation') + | |
82 | + content_tag('div', categories_selection_html, :id => 'categories_container_wrapper'), | |
83 | + :id => 'categories-container' | |
81 | 84 | end |
82 | 85 | |
83 | 86 | def select_for_categories(categories, level = 0) | ... | ... |
app/helpers/profile_editor_helper.rb
... | ... | @@ -141,8 +141,9 @@ module ProfileEditorHelper |
141 | 141 | ) |
142 | 142 | end |
143 | 143 | |
144 | - def control_panel_button(title, icon, url) | |
145 | - link_to title, url, :class => 'control-panel-%s' % icon | |
144 | + def control_panel_button(title, icon, url, html_options = {}) | |
145 | + html_options ||= {} | |
146 | + link_to title, url, html_options.merge(:class => 'control-panel-%s' % icon) | |
146 | 147 | end |
147 | 148 | |
148 | 149 | def unchangeable_privacy_field(profile) | ... | ... |
app/helpers/profile_helper.rb
... | ... | @@ -190,4 +190,22 @@ module ProfileHelper |
190 | 190 | end |
191 | 191 | end |
192 | 192 | |
193 | + def display_custom_field(title, profile, field, force = false) | |
194 | + unless force || profile.may_display_field_to?(field, user) | |
195 | + return | |
196 | + end | |
197 | + value = profile.custom_fields[field][:value] | |
198 | + !value.blank? ? content_tag('tr', content_tag('td', title) + content_tag('td', value)) : '' | |
199 | + end | |
200 | + | |
201 | + def display_custom_fields(profile) | |
202 | + fields = [] | |
203 | + profile.custom_fields.each { |custom_field_key,custom_field_data| | |
204 | + if !profile.fields_privacy.blank? && profile.fields_privacy.include?(custom_field_key) | |
205 | + fields << display_custom_field(custom_field_data[:title], profile, custom_field_key) if profile.fields_privacy[custom_field_key] == 'public' | |
206 | + end | |
207 | + } | |
208 | + fields.size >= 1 ? content_tag('tr', content_tag('th', _('Custom Fields'), { :colspan => 2 })) + fields.join.html_safe : '' | |
209 | + end | |
210 | + | |
193 | 211 | end | ... | ... |
app/helpers/search_helper.rb
... | ... | @@ -106,6 +106,10 @@ module SearchHelper |
106 | 106 | end |
107 | 107 | end |
108 | 108 | |
109 | + def city_with_state_for_profile(p) | |
110 | + city_with_state(p.region) || [p.city, p.state].compact.reject(&:blank?).join(', ') | |
111 | + end | |
112 | + | |
109 | 113 | def display_selector(asset, display, float = 'right') |
110 | 114 | display = nil if display.blank? |
111 | 115 | display ||= asset_class(asset).default_search_display | ... | ... |
... | ... | @@ -0,0 +1,23 @@ |
1 | +module TaskHelper | |
2 | + | |
3 | + def task_email_template(description, email_templates, task, include_blank=true) | |
4 | + return '' unless email_templates.present? | |
5 | + | |
6 | + content_tag( | |
7 | + :div, | |
8 | + labelled_form_field(description, select_tag("tasks[#{task.id}][task][email_template_id]", options_from_collection_for_select(email_templates, :id, :name), :include_blank => include_blank, 'data-url' => url_for(:controller => 'profile_email_templates', :action => 'show_parsed', :profile => profile.identifier))), | |
9 | + :class => 'template-selection' | |
10 | + ) | |
11 | + end | |
12 | + | |
13 | + def task_action action | |
14 | + base_url = { action: action } | |
15 | + url_for(base_url.merge(filter_params)) | |
16 | + end | |
17 | + | |
18 | + def filter_params | |
19 | + filter_fields = ['filter_type', 'filter_text', 'filter_responsible', 'filter_tags'] | |
20 | + params.select {|filter| filter if filter_fields.include? filter } | |
21 | + end | |
22 | + | |
23 | +end | ... | ... |
app/helpers/tinymce_helper.rb
... | ... | @@ -17,9 +17,10 @@ module TinymceHelper |
17 | 17 | searchreplace wordcount visualblocks visualchars code fullscreen |
18 | 18 | insertdatetime media nonbreaking save table contextmenu directionality |
19 | 19 | emoticons template paste textcolor colorpicker textpattern], |
20 | + :image_advtab => true, | |
20 | 21 | :language => tinymce_language |
21 | 22 | |
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 | + options[:toolbar1] = "fullscreen | insertfile undo redo | copy paste | bold italic underline | styleselect fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image" | |
23 | 24 | if options[:mode] == 'simple' |
24 | 25 | options[:menubar] = false |
25 | 26 | else | ... | ... |
app/helpers/users_helper.rb
... | ... | @@ -14,7 +14,7 @@ module UsersHelper |
14 | 14 | select_field = select_tag(:filter, options, :onchange => onchange) |
15 | 15 | content_tag('div', |
16 | 16 | content_tag('strong', _('Filter')) + ': ' + select_field, |
17 | - :class => "environment-users-customize-search" | |
17 | + :class => "environment-profiles-customize-search" | |
18 | 18 | ) |
19 | 19 | end |
20 | 20 | ... | ... |
app/mailers/scrap_notifier.rb
app/mailers/task_mailer.rb
1 | 1 | class TaskMailer < ActionMailer::Base |
2 | 2 | |
3 | + include EmailTemplateHelper | |
4 | + | |
3 | 5 | def target_notification(task, message) |
4 | 6 | @message = extract_message(message) |
5 | 7 | @target = task.target.name |
6 | 8 | @environment = task.environment.name |
7 | 9 | @url = generate_environment_url(task, :controller => 'home') |
8 | - url_for_tasks_list = task.target.kind_of?(Environment) ? '' : url_for(task.target.tasks_url) | |
10 | + url_for_tasks_list = task.target.kind_of?(Environment) ? '' : url_for(task.target.tasks_url.merge(:script_name => Noosfero.root('/'))) | |
9 | 11 | @tasks_url = url_for_tasks_list |
10 | 12 | |
11 | 13 | mail( |
... | ... | @@ -34,10 +36,12 @@ class TaskMailer < ActionMailer::Base |
34 | 36 | @environment = task.requestor.environment.name |
35 | 37 | @url = url_for(:host => task.requestor.environment.default_hostname, :controller => 'home') |
36 | 38 | |
37 | - mail( | |
39 | + mail_with_template( | |
38 | 40 | to: task.requestor.notification_emails, |
39 | 41 | from: self.class.generate_from(task), |
40 | - subject: '[%s] %s' % [task.requestor.environment.name, task.target_notification_description] | |
42 | + subject: '[%s] %s' % [task.requestor.environment.name, task.target_notification_description], | |
43 | + email_template: task.email_template, | |
44 | + template_params: {:environment => task.requestor.environment, :task => task, :message => @message, :url => @url, :requestor => task.requestor} | |
41 | 45 | ) |
42 | 46 | end |
43 | 47 | |
... | ... | @@ -56,7 +60,7 @@ class TaskMailer < ActionMailer::Base |
56 | 60 | end |
57 | 61 | |
58 | 62 | def generate_environment_url(task, url = {}) |
59 | - url_for(Noosfero.url_options.merge(:host => task.environment.default_hostname).merge(url)) | |
63 | + url_for(Noosfero.url_options.merge(:host => task.environment.default_hostname).merge(url).merge(:script_name => Noosfero.root('/'))) | |
60 | 64 | end |
61 | 65 | |
62 | 66 | end | ... | ... |
app/mailers/user_mailer.rb
1 | 1 | class UserMailer < ActionMailer::Base |
2 | + | |
3 | + include EmailTemplateHelper | |
4 | + | |
2 | 5 | def activation_email_notify(user) |
3 | 6 | user_email = "#{user.login}@#{user.email_domain}" |
4 | 7 | @name = user.name |
... | ... | @@ -22,10 +25,12 @@ class UserMailer < ActionMailer::Base |
22 | 25 | @redirection = (true if user.return_to) |
23 | 26 | @join = (user.community_to_join if user.community_to_join) |
24 | 27 | |
25 | - mail( | |
28 | + mail_with_template( | |
26 | 29 | from: "#{user.environment.name} <#{user.environment.contact_email}>", |
27 | 30 | to: user.email, |
28 | 31 | subject: _("[%s] Activate your account") % [user.environment.name], |
32 | + template_params: {:environment => user.environment, :activation_code => @activation_code, :redirection => @redirection, :join => @join}, | |
33 | + email_template: user.environment.email_templates.find_by_template_type(:user_activation), | |
29 | 34 | ) |
30 | 35 | end |
31 | 36 | ... | ... |
app/models/abuse_complaint.rb
app/models/add_friend.rb
... | ... | @@ -14,6 +14,9 @@ class AddFriend < Task |
14 | 14 | alias :friend :target |
15 | 15 | alias :friend= :target= |
16 | 16 | |
17 | + validates :requestor, :kind_of => { :kind => Person } | |
18 | + validates :target, :kind_of => { :kind => Person } | |
19 | + | |
17 | 20 | after_create do |task| |
18 | 21 | TaskMailer.invitation_notification(task).deliver unless task.friend |
19 | 22 | remove_from_suggestion_list(task) |
... | ... | @@ -54,7 +57,7 @@ class AddFriend < Task |
54 | 57 | end |
55 | 58 | |
56 | 59 | def remove_from_suggestion_list(task) |
57 | - suggestion = task.requestor.profile_suggestions.find_by_suggestion_id task.target.id | |
60 | + suggestion = task.requestor.suggested_profiles.find_by_suggestion_id task.target.id | |
58 | 61 | suggestion.disable if suggestion |
59 | 62 | end |
60 | 63 | end | ... | ... |
app/models/add_member.rb
... | ... | @@ -2,6 +2,9 @@ class AddMember < Task |
2 | 2 | |
3 | 3 | validates_presence_of :requestor_id, :target_id |
4 | 4 | |
5 | + validates :requestor, kind_of: {kind: Person} | |
6 | + validates :target, kind_of: {kind: Organization} | |
7 | + | |
5 | 8 | alias :person :requestor |
6 | 9 | alias :person= :requestor= |
7 | 10 | |
... | ... | @@ -26,7 +29,8 @@ class AddMember < Task |
26 | 29 | end |
27 | 30 | |
28 | 31 | def information |
29 | - {:message => _('%{requestor} wants to be a member of this community.')} | |
32 | + {:message => _("%{requestor} wants to be a member of '%{organization}'."), | |
33 | + variables: {requestor: requestor.name, organization: organization.name}} | |
30 | 34 | end |
31 | 35 | |
32 | 36 | def accept_details |
... | ... | @@ -42,7 +46,7 @@ class AddMember < Task |
42 | 46 | end |
43 | 47 | |
44 | 48 | def target_notification_description |
45 | - _('%{requestor} wants to be a member of this community.') % {:requestor => requestor.name} | |
49 | + _("%{requestor} wants to be a member of '%{organization}'.") % {:requestor => requestor.name, :organization => organization.name} | |
46 | 50 | end |
47 | 51 | |
48 | 52 | def target_notification_message | ... | ... |
app/models/approve_article.rb
1 | 1 | class ApproveArticle < Task |
2 | 2 | validates_presence_of :requestor_id, :target_id |
3 | 3 | |
4 | + validates :requestor, kind_of: {kind: Person} | |
5 | + validate :allowed_requestor | |
6 | + | |
7 | + def allowed_requestor | |
8 | + if target | |
9 | + if target.person? && requestor != target | |
10 | + self.errors.add(:requestor, _('You can not post articles to other users.')) | |
11 | + end | |
12 | + if target.organization? && !target.members.include?(requestor) && target.environment.portal_community != target | |
13 | + self.errors.add(:requestor, _('Only members can post articles on communities.')) | |
14 | + end | |
15 | + end | |
16 | + end | |
17 | + | |
4 | 18 | def article_title |
5 | 19 | article ? article.title : _('(The original text was removed)') |
6 | 20 | end |
7 | - | |
21 | + | |
8 | 22 | def article |
9 | 23 | Article.find_by_id data[:article_id] |
10 | 24 | end |
... | ... | @@ -82,10 +96,6 @@ class ApproveArticle < Task |
82 | 96 | true |
83 | 97 | end |
84 | 98 | |
85 | - def reject_details | |
86 | - true | |
87 | - end | |
88 | - | |
89 | 99 | def default_decision |
90 | 100 | if article |
91 | 101 | 'skip' |
... | ... | @@ -128,4 +138,9 @@ class ApproveArticle < Task |
128 | 138 | message |
129 | 139 | end |
130 | 140 | |
141 | + def request_is_member_of_target | |
142 | + unless requestor.is_member_of?(target) | |
143 | + errors.add(:approve_article, N_('Requestor must be a member of target.')) | |
144 | + end | |
145 | + end | |
131 | 146 | end | ... | ... |
app/models/approve_comment.rb
app/models/article.rb
1 | - | |
2 | 1 | class Article < ActiveRecord::Base |
3 | 2 | |
4 | 3 | attr_accessible :name, :body, :abstract, :profile, :tag_list, :parent, |
5 | 4 | :allow_members_to_edit, :translation_of_id, :language, |
6 | 5 | :license_id, :parent_id, :display_posts_in_current_language, |
7 | 6 | :category_ids, :posts_per_page, :moderate_comments, |
8 | - :accept_comments, :feed, :published, :source, | |
7 | + :accept_comments, :feed, :published, :source, :source_name, | |
9 | 8 | :highlighted, :notify_comments, :display_hits, :slug, |
10 | 9 | :external_feed_builder, :display_versions, :external_link, |
11 | - :image_builder, :show_to_followers | |
10 | + :author, :published_at, :person_followers, :show_to_followers, :image_builder | |
12 | 11 | |
13 | 12 | acts_as_having_image |
14 | 13 | |
... | ... | @@ -25,6 +24,16 @@ class Article < ActiveRecord::Base |
25 | 24 | :display => %w[full] |
26 | 25 | } |
27 | 26 | |
27 | + def initialize(*params) | |
28 | + super | |
29 | + | |
30 | + if !params.blank? && params.first.has_key?(:profile) && !params.first[:profile].blank? | |
31 | + profile = params.first[:profile] | |
32 | + self.published = false unless profile.public? | |
33 | + end | |
34 | + | |
35 | + end | |
36 | + | |
28 | 37 | def self.default_search_display |
29 | 38 | 'full' |
30 | 39 | end |
... | ... | @@ -61,6 +70,10 @@ class Article < ActiveRecord::Base |
61 | 70 | belongs_to :last_changed_by, :class_name => 'Person', :foreign_key => 'last_changed_by_id' |
62 | 71 | belongs_to :created_by, :class_name => 'Person', :foreign_key => 'created_by_id' |
63 | 72 | |
73 | + #Article followers relation | |
74 | + has_many :article_followers, :dependent => :destroy | |
75 | + has_many :person_followers, :class_name => 'Person', :through => :article_followers, :source => :person | |
76 | + | |
64 | 77 | has_many :comments, :class_name => 'Comment', :foreign_key => 'source_id', :dependent => :destroy, :order => 'created_at asc' |
65 | 78 | |
66 | 79 | has_many :article_categorizations, :conditions => [ 'articles_categories.virtual = ?', false ] |
... | ... | @@ -86,6 +99,8 @@ class Article < ActiveRecord::Base |
86 | 99 | belongs_to :translation_of, :class_name => 'Article', :foreign_key => :translation_of_id |
87 | 100 | before_destroy :rotate_translations |
88 | 101 | |
102 | + acts_as_voteable | |
103 | + | |
89 | 104 | before_create do |article| |
90 | 105 | article.published_at ||= Time.now |
91 | 106 | if article.reference_article && !article.parent |
... | ... | @@ -117,9 +132,11 @@ class Article < ActiveRecord::Base |
117 | 132 | {:include => 'categories_including_virtual', :conditions => { 'categories.id' => category.id }} |
118 | 133 | } |
119 | 134 | |
135 | + include TimeScopes | |
136 | + | |
120 | 137 | scope :by_range, lambda { |range| { |
121 | 138 | :conditions => [ |
122 | - 'published_at BETWEEN :start_date AND :end_date', { :start_date => range.first, :end_date => range.last } | |
139 | + 'articles.published_at BETWEEN :start_date AND :end_date', { :start_date => range.first, :end_date => range.last } | |
123 | 140 | ] |
124 | 141 | }} |
125 | 142 | |
... | ... | @@ -248,7 +265,7 @@ class Article < ActiveRecord::Base |
248 | 265 | } |
249 | 266 | |
250 | 267 | scope :public, |
251 | - :conditions => [ "advertise = ? AND published = ? AND profiles.visible = ? AND profiles.public_profile = ?", true, true, true, true ], :joins => [:profile] | |
268 | + :conditions => [ "articles.advertise = ? AND articles.published = ? AND profiles.visible = ? AND profiles.public_profile = ?", true, true, true, true ], :joins => [:profile] | |
252 | 269 | |
253 | 270 | scope :more_recent, |
254 | 271 | :conditions => [ "advertise = ? AND published = ? AND profiles.visible = ? AND profiles.public_profile = ? AND |
... | ... | @@ -491,11 +508,11 @@ class Article < ActiveRecord::Base |
491 | 508 | return [] if user.nil? || (profile && !profile.public? && !user.follows?(profile)) |
492 | 509 | where( |
493 | 510 | [ |
494 | - "published = ? OR last_changed_by_id = ? OR profile_id = ? OR ? | |
495 | - OR (show_to_followers = ? AND ?)", true, user.id, user.id, | |
511 | + "published = ? OR last_changed_by_id = ? OR profile_id = ? OR ? | |
512 | + OR (show_to_followers = ? AND ? AND profile_id IN (?))", true, user.id, user.id, | |
496 | 513 | profile.nil? ? false : user.has_permission?(:view_private_content, profile), |
497 | - true, user.follows?(profile) | |
498 | - ] | |
514 | + true, (profile.nil? ? true : user.follows?(profile)), ( profile.nil? ? (user.friends.select('profiles.id')) : [profile.id]) | |
515 | + ] | |
499 | 516 | ) |
500 | 517 | } |
501 | 518 | |
... | ... | @@ -509,7 +526,7 @@ class Article < ActiveRecord::Base |
509 | 526 | |
510 | 527 | def display_to?(user = nil) |
511 | 528 | if published? |
512 | - profile.display_info_to?(user) | |
529 | + (profile.secret? || !profile.visible?) ? profile.display_info_to?(user) : true | |
513 | 530 | else |
514 | 531 | if !user |
515 | 532 | false |
... | ... | @@ -567,25 +584,24 @@ class Article < ActiveRecord::Base |
567 | 584 | profile.visible? && profile.public? && published? |
568 | 585 | end |
569 | 586 | |
570 | - | |
571 | - def copy(options = {}) | |
587 | + def copy_without_save(options = {}) | |
572 | 588 | attrs = attributes.reject! { |key, value| ATTRIBUTES_NOT_COPIED.include?(key.to_sym) } |
573 | 589 | attrs.merge!(options) |
574 | 590 | object = self.class.new |
575 | 591 | attrs.each do |key, value| |
576 | 592 | object.send(key.to_s+'=', value) |
577 | 593 | end |
594 | + object | |
595 | + end | |
596 | + | |
597 | + def copy(options = {}) | |
598 | + object = copy_without_save(options) | |
578 | 599 | object.save |
579 | 600 | object |
580 | 601 | end |
581 | 602 | |
582 | 603 | def copy!(options = {}) |
583 | - attrs = attributes.reject! { |key, value| ATTRIBUTES_NOT_COPIED.include?(key.to_sym) } | |
584 | - attrs.merge!(options) | |
585 | - object = self.class.new | |
586 | - attrs.each do |key, value| | |
587 | - object.send(key.to_s+'=', value) | |
588 | - end | |
604 | + object = copy_without_save(options) | |
589 | 605 | object.save! |
590 | 606 | object |
591 | 607 | end |
... | ... | @@ -615,6 +631,11 @@ class Article < ActiveRecord::Base |
615 | 631 | self.hits += 1 |
616 | 632 | end |
617 | 633 | |
634 | + def self.hit(articles) | |
635 | + Article.where(:id => articles.map(&:id)).update_all('hits = hits + 1') | |
636 | + articles.each { |a| a.hits += 1 } | |
637 | + end | |
638 | + | |
618 | 639 | def can_display_hits? |
619 | 640 | true |
620 | 641 | end |
... | ... | @@ -623,6 +644,14 @@ class Article < ActiveRecord::Base |
623 | 644 | can_display_hits? && display_hits |
624 | 645 | end |
625 | 646 | |
647 | + def display_media_panel? | |
648 | + can_display_media_panel? && environment.enabled?('media_panel') | |
649 | + end | |
650 | + | |
651 | + def can_display_media_panel? | |
652 | + false | |
653 | + end | |
654 | + | |
626 | 655 | def image? |
627 | 656 | false |
628 | 657 | end |
... | ... | @@ -692,6 +721,11 @@ class Article < ActiveRecord::Base |
692 | 721 | person ? person.id : nil |
693 | 722 | end |
694 | 723 | |
724 | + #FIXME make this test | |
725 | + def author_custom_image(size = :icon) | |
726 | + author ? author.profile_custom_image(size) : nil | |
727 | + end | |
728 | + | |
695 | 729 | def version_license(version_number = nil) |
696 | 730 | return license if version_number.nil? |
697 | 731 | profile.environment.licenses.find_by_id(get_version(version_number).license_id) |
... | ... | @@ -713,8 +747,9 @@ class Article < ActiveRecord::Base |
713 | 747 | paragraphs.empty? ? '' : paragraphs.first.to_html |
714 | 748 | end |
715 | 749 | |
716 | - def lead | |
717 | - abstract.blank? ? first_paragraph.html_safe : abstract.html_safe | |
750 | + def lead(length = nil) | |
751 | + content = abstract.blank? ? first_paragraph.html_safe : abstract.html_safe | |
752 | + length.present? ? content.truncate(length) : content | |
718 | 753 | end |
719 | 754 | |
720 | 755 | def short_lead |
... | ... | @@ -781,6 +816,14 @@ class Article < ActiveRecord::Base |
781 | 816 | true |
782 | 817 | end |
783 | 818 | |
819 | + def view_page | |
820 | + "content_viewer/view_page" | |
821 | + end | |
822 | + | |
823 | + def to_liquid | |
824 | + HashWithIndifferentAccess.new :name => name, :abstract => abstract, :body => body, :id => id, :parent_id => parent_id, :author => author | |
825 | + end | |
826 | + | |
784 | 827 | private |
785 | 828 | |
786 | 829 | def sanitize_tag_list | ... | ... |
app/models/article_block.rb
... | ... | @@ -3,7 +3,15 @@ class ArticleBlock < Block |
3 | 3 | attr_accessible :article_id |
4 | 4 | |
5 | 5 | def self.description |
6 | - _('Display one of your contents') | |
6 | + _('Display one of your contents.') | |
7 | + end | |
8 | + | |
9 | + def self.short_description | |
10 | + _('Show one article') | |
11 | + end | |
12 | + | |
13 | + def self.pretty_name | |
14 | + _('Article') | |
7 | 15 | end |
8 | 16 | |
9 | 17 | def help | ... | ... |
app/models/block.rb
1 | 1 | class Block < ActiveRecord::Base |
2 | 2 | |
3 | - attr_accessible :title, :display, :limit, :box_id, :posts_per_page, :visualization_format, :language, :display_user, :box, :fixed | |
3 | + attr_accessible :title, :display, :limit, :box_id, :posts_per_page, | |
4 | + :visualization_format, :language, :display_user, | |
5 | + :box, :edit_modes, :move_modes, :mirror | |
4 | 6 | |
5 | 7 | # to be able to generate HTML |
6 | 8 | include ActionView::Helpers::UrlHelper |
... | ... | @@ -13,17 +15,29 @@ class Block < ActiveRecord::Base |
13 | 15 | |
14 | 16 | acts_as_list :scope => :box |
15 | 17 | belongs_to :box |
18 | + belongs_to :mirror_block, :class_name => "Block" | |
19 | + has_many :observers, :class_name => "Block", :foreign_key => "mirror_block_id" | |
16 | 20 | |
17 | 21 | acts_as_having_settings |
18 | 22 | |
19 | 23 | scope :enabled, :conditions => { :enabled => true } |
20 | 24 | |
25 | + after_save do |block| | |
26 | + if block.owner.kind_of?(Profile) && block.owner.is_template? && block.mirror? | |
27 | + block.observers.each do |observer| | |
28 | + observer.copy_from(block) | |
29 | + observer.title = block.title | |
30 | + observer.save | |
31 | + end | |
32 | + end | |
33 | + end | |
34 | + | |
21 | 35 | def embedable? |
22 | 36 | false |
23 | 37 | end |
24 | 38 | |
25 | 39 | def get_limit |
26 | - [0,limit].max | |
40 | + [0,limit.to_i].max | |
27 | 41 | end |
28 | 42 | |
29 | 43 | def embed_code |
... | ... | @@ -110,8 +124,13 @@ class Block < ActiveRecord::Base |
110 | 124 | # * <tt>'all'</tt>: the block is always displayed |
111 | 125 | settings_items :language, :type => :string, :default => 'all' |
112 | 126 | |
113 | - # The block can be configured to be fixed. Only can be edited by environment admins | |
114 | - settings_items :fixed, :type => :boolean, :default => false | |
127 | + # The block can be configured to define the edition modes options. Only can be edited by environment admins | |
128 | + # It can assume the following values: | |
129 | + # | |
130 | + # * <tt>'all'</tt>: the block owner has all edit options for this block | |
131 | + # * <tt>'none'</tt>: the block owner can't do anything with the block | |
132 | + settings_items :edit_modes, :type => :string, :default => 'all' | |
133 | + settings_items :move_modes, :type => :string, :default => 'all' | |
115 | 134 | |
116 | 135 | # returns the description of the block, used when the user sees a list of |
117 | 136 | # blocks to choose one to include in the design. |
... | ... | @@ -122,6 +141,36 @@ class Block < ActiveRecord::Base |
122 | 141 | '(dummy)' |
123 | 142 | end |
124 | 143 | |
144 | + def self.short_description | |
145 | + self.pretty_name | |
146 | + end | |
147 | + | |
148 | + def self.icon | |
149 | + "/images/icon_block.png" | |
150 | + end | |
151 | + | |
152 | + def self.icon_path | |
153 | + basename = self.name.split('::').last.underscore | |
154 | + File.join('blocks', basename, 'icon.png') | |
155 | + end | |
156 | + | |
157 | + def self.pretty_name | |
158 | + self.name.split('::').last.gsub('Block','') | |
159 | + end | |
160 | + | |
161 | + def self.default_icon_path | |
162 | + 'icon_block.png' | |
163 | + end | |
164 | + | |
165 | + def self.preview_path | |
166 | + base_name = self.name.split('::').last.underscore | |
167 | + File.join('blocks', base_name,'previews') | |
168 | + end | |
169 | + | |
170 | + def self.default_preview_path | |
171 | + "block_preview.png" | |
172 | + end | |
173 | + | |
125 | 174 | # Returns the content to be used for this block. |
126 | 175 | # |
127 | 176 | # This method can return several types of objects: |
... | ... | @@ -148,7 +197,11 @@ class Block < ActiveRecord::Base |
148 | 197 | |
149 | 198 | # Is this block editable? (Default to <tt>false</tt>) |
150 | 199 | def editable? |
151 | - true | |
200 | + self.edit_modes == "all" | |
201 | + end | |
202 | + | |
203 | + def movable? | |
204 | + self.move_modes == "all" | |
152 | 205 | end |
153 | 206 | |
154 | 207 | # must always return false, except on MainBlock clas. |
... | ... | @@ -228,6 +281,21 @@ class Block < ActiveRecord::Base |
228 | 281 | } |
229 | 282 | end |
230 | 283 | |
284 | + def edit_block_options | |
285 | + @edit_options ||= { | |
286 | + 'all' => _('Can be modified'), | |
287 | + 'none' => _('Cannot be modified') | |
288 | + } | |
289 | + end | |
290 | + | |
291 | + def move_block_options | |
292 | + @move_options ||= { | |
293 | + 'all' => _('Can be moved'), | |
294 | + 'none' => _('Cannot be moved') | |
295 | + } | |
296 | + end | |
297 | + | |
298 | + | |
231 | 299 | def duplicate |
232 | 300 | duplicated_block = self.dup |
233 | 301 | duplicated_block.display = 'never' |
... | ... | @@ -243,6 +311,10 @@ class Block < ActiveRecord::Base |
243 | 311 | self.position = block.position |
244 | 312 | end |
245 | 313 | |
314 | + def add_observer(block) | |
315 | + self.observers << block | |
316 | + end | |
317 | + | |
246 | 318 | private |
247 | 319 | |
248 | 320 | def home_page_path | ... | ... |
app/models/blog.rb
... | ... | @@ -76,9 +76,12 @@ class Blog < Folder |
76 | 76 | end |
77 | 77 | |
78 | 78 | settings_items :visualization_format, :type => :string, :default => 'full' |
79 | - validates_inclusion_of :visualization_format, :in => [ 'full', 'short', 'short+pic' ], :if => :visualization_format | |
79 | + validates_inclusion_of :visualization_format, | |
80 | + :in => [ 'full', 'short', 'short+pic', 'compact'], | |
81 | + :if => :visualization_format | |
80 | 82 | |
81 | - settings_items :display_posts_in_current_language, :type => :boolean, :default => false | |
83 | + settings_items :display_posts_in_current_language, | |
84 | + :type => :boolean, :default => false | |
82 | 85 | |
83 | 86 | alias :display_posts_in_current_language? :display_posts_in_current_language |
84 | 87 | ... | ... |
app/models/change_password.rb
... | ... | @@ -18,6 +18,8 @@ class ChangePassword < Task |
18 | 18 | |
19 | 19 | validates_presence_of :requestor |
20 | 20 | |
21 | + validates :requestor, kind_of: {kind: Person} | |
22 | + | |
21 | 23 | ################################################### |
22 | 24 | # validations for updating a ChangePassword task |
23 | 25 | |
... | ... | @@ -26,6 +28,13 @@ class ChangePassword < Task |
26 | 28 | validates_presence_of :password_confirmation, :on => :update, :if => lambda { |change| change.status != Task::Status::CANCELLED } |
27 | 29 | validates_confirmation_of :password, :if => lambda { |change| change.status != Task::Status::CANCELLED } |
28 | 30 | |
31 | + before_save :set_email_template | |
32 | + | |
33 | + def set_email_template | |
34 | + template = environment.email_templates.find_by_template_type(:user_change_password) | |
35 | + data[:email_template_id] = template.id unless template.nil? | |
36 | + end | |
37 | + | |
29 | 38 | def environment |
30 | 39 | requestor.environment unless requestor.nil? |
31 | 40 | end | ... | ... |
app/models/chat_message.rb
app/models/comment.rb
... | ... | @@ -20,6 +20,8 @@ class Comment < ActiveRecord::Base |
20 | 20 | |
21 | 21 | scope :without_reply, :conditions => ['reply_of_id IS NULL'] |
22 | 22 | |
23 | + include TimeScopes | |
24 | + | |
23 | 25 | # unauthenticated authors: |
24 | 26 | validates_presence_of :name, :if => (lambda { |record| !record.email.blank? }) |
25 | 27 | validates_presence_of :email, :if => (lambda { |record| !record.name.blank? }) |
... | ... | @@ -32,11 +34,13 @@ class Comment < ActiveRecord::Base |
32 | 34 | rec.errors.add(:name, _('{fn} can only be informed for unauthenticated authors').fix_i18n) |
33 | 35 | end |
34 | 36 | end |
35 | - | |
37 | + | |
36 | 38 | acts_as_having_settings |
37 | 39 | |
38 | 40 | xss_terminate :only => [ :body, :title, :name ], :on => 'validation' |
39 | 41 | |
42 | + acts_as_voteable | |
43 | + | |
40 | 44 | def comment_root |
41 | 45 | (reply_of && reply_of.comment_root) || self |
42 | 46 | end |
... | ... | @@ -65,6 +69,11 @@ class Comment < ActiveRecord::Base |
65 | 69 | author ? author.url : nil |
66 | 70 | end |
67 | 71 | |
72 | + #FIXME make this test | |
73 | + def author_custom_image(size = :icon) | |
74 | + author ? author.profile_custom_image(size) : nil | |
75 | + end | |
76 | + | |
68 | 77 | def url |
69 | 78 | article.view_url.merge(:anchor => anchor) |
70 | 79 | end | ... | ... |
app/models/communities_block.rb
... | ... | @@ -3,9 +3,17 @@ class CommunitiesBlock < ProfileListBlock |
3 | 3 | attr_accessible :accessor_id, :accessor_type, :role_id, :resource_id, :resource_type |
4 | 4 | |
5 | 5 | def self.description |
6 | + _("<p>Display all of your communities.</p><p>You could choose the amount of communities will be displayed and you could priorize that profiles with images.</p> <p>The view all button is always present in the block.</p>") | |
7 | + end | |
8 | + | |
9 | + def self.short_description | |
6 | 10 | _('Communities') |
7 | 11 | end |
8 | 12 | |
13 | + def self.pretty_name | |
14 | + _('Communities Block') | |
15 | + end | |
16 | + | |
9 | 17 | def default_title |
10 | 18 | n_('{#} community', '{#} communities', profile_count) |
11 | 19 | end | ... | ... |
app/models/community.rb
... | ... | @@ -86,8 +86,8 @@ class Community < Organization |
86 | 86 | {:title => _('Community Info and settings'), :icon => 'edit-profile-group'} |
87 | 87 | end |
88 | 88 | |
89 | - def activities | |
90 | - Scrap.find_by_sql("SELECT id, updated_at, '#{Scrap.to_s}' AS klass FROM #{Scrap.table_name} WHERE scraps.receiver_id = #{self.id} AND scraps.scrap_id IS NULL UNION SELECT id, updated_at, '#{ActionTracker::Record.to_s}' AS klass FROM #{ActionTracker::Record.table_name} WHERE action_tracker.target_id = #{self.id} and action_tracker.verb != 'join_community' and action_tracker.verb != 'leave_scrap' UNION SELECT at.id, at.updated_at, '#{ActionTracker::Record.to_s}' AS klass FROM #{ActionTracker::Record.table_name} at INNER JOIN articles a ON at.target_id = a.id WHERE a.profile_id = #{self.id} AND at.target_type = 'Article' ORDER BY updated_at DESC") | |
89 | + def exclude_verbs_on_activities | |
90 | + %w[join_community leave_scrap] | |
91 | 91 | end |
92 | 92 | |
93 | 93 | end | ... | ... |
app/models/create_community.rb
... | ... | @@ -3,6 +3,9 @@ class CreateCommunity < Task |
3 | 3 | validates_presence_of :requestor_id, :target_id |
4 | 4 | validates_presence_of :name |
5 | 5 | |
6 | + validates :requestor, kind_of: {kind: Person} | |
7 | + validates :target, kind_of: {kind: Environment} | |
8 | + | |
6 | 9 | alias :environment :target |
7 | 10 | alias :environment= :target= |
8 | 11 | |
... | ... | @@ -56,10 +59,6 @@ class CreateCommunity < Task |
56 | 59 | end |
57 | 60 | end |
58 | 61 | |
59 | - def reject_details | |
60 | - true | |
61 | - end | |
62 | - | |
63 | 62 | # tells if this request was rejected |
64 | 63 | def rejected? |
65 | 64 | self.status == Task::Status::CANCELLED | ... | ... |
app/models/create_enterprise.rb
... | ... | @@ -27,6 +27,8 @@ class CreateEnterprise < Task |
27 | 27 | # checks for actual attributes |
28 | 28 | validates_presence_of :requestor_id, :target_id |
29 | 29 | |
30 | + validates :requestor, kind_of: {kind: Person} | |
31 | + | |
30 | 32 | # checks for admins required attributes |
31 | 33 | DATA_FIELDS.each do |attribute| |
32 | 34 | validates_presence_of attribute, :if => lambda { |obj| obj.environment.required_enterprise_fields.include?(attribute) } |
... | ... | @@ -164,10 +166,6 @@ class CreateEnterprise < Task |
164 | 166 | {:message => _('%{requestor} wants to create enterprise %{subject}.')} |
165 | 167 | end |
166 | 168 | |
167 | - def reject_details | |
168 | - true | |
169 | - end | |
170 | - | |
171 | 169 | def task_created_message |
172 | 170 | _('Your request for registering enterprise "%{enterprise}" at %{environment} was just received. It will be reviewed by the validator organization of your choice, according to its methods and criteria. |
173 | 171 | ... | ... |
app/models/email_activation.rb
1 | 1 | class EmailActivation < Task |
2 | 2 | |
3 | 3 | validates_presence_of :requestor_id, :target_id |
4 | + | |
5 | + validates :requestor, kind_of: {kind: Person} | |
6 | + validates :target, kind_of: {kind: Environment} | |
7 | + | |
4 | 8 | validate :already_requested, :on => :create |
5 | 9 | |
6 | 10 | alias :environment :target |
7 | 11 | alias :person :requestor |
8 | 12 | |
9 | 13 | def already_requested |
10 | - if !self.requestor.nil? && self.requestor.user.email_activation_pending? | |
14 | + if !self.requestor.nil? && self.requestor.person? && self.requestor.user.email_activation_pending? | |
11 | 15 | self.errors.add(:base, _('You have already requested activation of your mailbox.')) |
12 | 16 | end |
13 | 17 | end | ... | ... |
... | ... | @@ -0,0 +1,50 @@ |
1 | +class EmailTemplate < ActiveRecord::Base | |
2 | + | |
3 | + belongs_to :owner, :polymorphic => true | |
4 | + | |
5 | + attr_accessible :template_type, :subject, :body, :owner, :name | |
6 | + | |
7 | + validates_presence_of :name | |
8 | + | |
9 | + validates :name, uniqueness: { scope: [:owner_type, :owner_id] } | |
10 | + | |
11 | + validates :template_type, uniqueness: { scope: [:owner_type, :owner_id] }, if: :unique_by_type? | |
12 | + | |
13 | + def parsed_body(params) | |
14 | + @parsed_body ||= parse(body, params) | |
15 | + end | |
16 | + | |
17 | + def parsed_subject(params) | |
18 | + @parsed_subject ||= parse(subject, params) | |
19 | + end | |
20 | + | |
21 | + def self.available_types | |
22 | + { | |
23 | + :task_rejection => {:description => _('Task Rejection'), :owner_type => Profile}, | |
24 | + :task_acceptance => {:description => _('Task Acceptance'), :owner_type => Profile}, | |
25 | + :organization_members => {:description => _('Organization Members'), :owner_type => Profile}, | |
26 | + :user_activation => {:description => _('User Activation'), :unique => true, :owner_type => Environment}, | |
27 | + :user_change_password => {:description => _('Change User Password'), :unique => true, :owner_type => Environment} | |
28 | + } | |
29 | + end | |
30 | + | |
31 | + def available_types | |
32 | + HashWithIndifferentAccess.new EmailTemplate.available_types.select {|k, v| owner.kind_of?(v[:owner_type])} | |
33 | + end | |
34 | + | |
35 | + def type_description | |
36 | + available_types.fetch(template_type, {})[:description] | |
37 | + end | |
38 | + | |
39 | + def unique_by_type? | |
40 | + available_types.fetch(template_type, {})[:unique] | |
41 | + end | |
42 | + | |
43 | + protected | |
44 | + | |
45 | + def parse(source, params) | |
46 | + template = Liquid::Template.parse(source) | |
47 | + template.render(HashWithIndifferentAccess.new(params)) | |
48 | + end | |
49 | + | |
50 | +end | ... | ... |
app/models/enterprise.rb
... | ... | @@ -15,12 +15,15 @@ class Enterprise < Organization |
15 | 15 | |
16 | 16 | N_('Enterprise') |
17 | 17 | |
18 | - has_many :products, :foreign_key => :profile_id, :dependent => :destroy, :order => 'name ASC' | |
18 | + acts_as_trackable after_add: proc{ |p, t| notify_activity t } | |
19 | + | |
20 | + has_many :products, :foreign_key => :profile_id, :dependent => :destroy | |
21 | + has_many :product_categories, :through => :products | |
19 | 22 | has_many :inputs, :through => :products |
20 | 23 | has_many :production_costs, :as => :owner |
21 | 24 | |
22 | 25 | has_many :favorite_enterprise_people |
23 | - has_many :fans, through: :favorite_enterprise_people, source: :person | |
26 | + has_many :fans, source: :person, through: :favorite_enterprise_people | |
24 | 27 | |
25 | 28 | def product_categories |
26 | 29 | ProductCategory.by_enterprise(self) |
... | ... | @@ -194,10 +197,6 @@ class Enterprise < Organization |
194 | 197 | true |
195 | 198 | end |
196 | 199 | |
197 | - def activities | |
198 | - Scrap.find_by_sql("SELECT id, updated_at, 'Scrap' AS klass FROM scraps WHERE scraps.receiver_id = #{self.id} AND scraps.scrap_id IS NULL UNION SELECT id, updated_at, 'ActionTracker::Record' AS klass FROM action_tracker WHERE action_tracker.target_id = #{self.id} UNION SELECT action_tracker.id, action_tracker.updated_at, 'ActionTracker::Record' AS klass FROM action_tracker INNER JOIN articles ON action_tracker.target_id = articles.id WHERE articles.profile_id = #{self.id} AND action_tracker.target_type = 'Article' ORDER BY updated_at DESC") | |
199 | - end | |
200 | - | |
201 | 200 | def catalog_url |
202 | 201 | { :profile => identifier, :controller => 'catalog'} |
203 | 202 | end |
... | ... | @@ -206,4 +205,9 @@ class Enterprise < Organization |
206 | 205 | '' |
207 | 206 | end |
208 | 207 | |
208 | + def followed_by? person | |
209 | + super or self.fans.where(id: person.id).count > 0 | |
210 | + end | |
211 | + | |
212 | + | |
209 | 213 | end | ... | ... |
app/models/enterprise_activation.rb
app/models/enterprise_homepage.rb
app/models/environment.rb
... | ... | @@ -3,7 +3,17 @@ |
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, :members_whitelist_enabled, :members_whitelist, :highlighted_news_amount, :portal_news_amount | |
6 | + attr_accessible :name, :is_default, :signup_welcome_text_subject, | |
7 | + :signup_welcome_text_body, :terms_of_use, | |
8 | + :message_for_disabled_enterprise, :news_amount_by_folder, | |
9 | + :default_language, :languages, :description, | |
10 | + :organization_approval_method, :enabled_plugins, | |
11 | + :enabled_features, :redirection_after_login, | |
12 | + :redirection_after_signup, :contact_email, :theme, | |
13 | + :reports_lower_bound, :noreply_email, | |
14 | + :signup_welcome_screen_body, :members_whitelist_enabled, | |
15 | + :members_whitelist, :highlighted_news_amount, | |
16 | + :portal_news_amount, :date_format | |
7 | 17 | |
8 | 18 | has_many :users |
9 | 19 | |
... | ... | @@ -11,14 +21,23 @@ class Environment < ActiveRecord::Base |
11 | 21 | |
12 | 22 | has_many :tasks, :dependent => :destroy, :as => 'target' |
13 | 23 | has_many :search_terms, :as => :context |
24 | + has_many :email_templates, :foreign_key => :owner_id | |
14 | 25 | |
15 | 26 | IDENTIFY_SCRIPTS = /(php[0-9s]?|[sp]htm[l]?|pl|py|cgi|rb)/ |
16 | 27 | |
28 | + validates_inclusion_of :date_format, | |
29 | + :in => [ 'numbers_with_year', 'numbers', | |
30 | + 'month_name_with_year', 'month_name', | |
31 | + 'past_time'], | |
32 | + :if => :date_format | |
33 | + | |
17 | 34 | def self.verify_filename(filename) |
18 | 35 | filename += '.txt' if File.extname(filename) =~ IDENTIFY_SCRIPTS |
19 | 36 | filename |
20 | 37 | end |
21 | 38 | |
39 | + NUMBER_OF_BOXES = 4 | |
40 | + | |
22 | 41 | PERMISSIONS['Environment'] = { |
23 | 42 | 'view_environment_admin_panel' => N_('View environment admin panel'), |
24 | 43 | 'edit_environment_features' => N_('Edit environment features'), |
... | ... | @@ -27,10 +46,12 @@ class Environment < ActiveRecord::Base |
27 | 46 | 'manage_environment_roles' => N_('Manage environment roles'), |
28 | 47 | 'manage_environment_validators' => N_('Manage environment validators'), |
29 | 48 | 'manage_environment_users' => N_('Manage environment users'), |
49 | + 'manage_environment_organizations' => N_('Manage environment organizations'), | |
30 | 50 | 'manage_environment_templates' => N_('Manage environment templates'), |
31 | 51 | 'manage_environment_licenses' => N_('Manage environment licenses'), |
32 | 52 | 'manage_environment_trusted_sites' => N_('Manage environment trusted sites'), |
33 | 53 | 'edit_appearance' => N_('Edit appearance'), |
54 | + 'manage_email_templates' => N_('Manage Email Templates'), | |
34 | 55 | } |
35 | 56 | |
36 | 57 | module Roles |
... | ... | @@ -72,7 +93,8 @@ class Environment < ActiveRecord::Base |
72 | 93 | 'edit_profile_design', |
73 | 94 | 'manage_products', |
74 | 95 | 'manage_friends', |
75 | - 'perform_task' | |
96 | + 'perform_task', | |
97 | + 'view_tasks' | |
76 | 98 | ] |
77 | 99 | ) |
78 | 100 | end |
... | ... | @@ -108,6 +130,7 @@ class Environment < ActiveRecord::Base |
108 | 130 | 'disable_select_city_for_contact' => _('Disable state/city select for contact form'), |
109 | 131 | 'disable_contact_person' => _('Disable contact for people'), |
110 | 132 | 'disable_contact_community' => _('Disable contact for groups/communities'), |
133 | + 'forbid_destroy_profile' => _('Forbid users of removing profiles'), | |
111 | 134 | |
112 | 135 | 'products_for_enterprises' => _('Enable products for enterprises'), |
113 | 136 | 'enterprise_registration' => _('Enterprise registration'), |
... | ... | @@ -147,7 +170,8 @@ class Environment < ActiveRecord::Base |
147 | 170 | 'site_homepage' => _('Redirects the user to the environment homepage.'), |
148 | 171 | 'user_profile_page' => _('Redirects the user to his profile page.'), |
149 | 172 | 'user_homepage' => _('Redirects the user to his homepage.'), |
150 | - 'user_control_panel' => _('Redirects the user to his control panel.') | |
173 | + 'user_control_panel' => _('Redirects the user to his control panel.'), | |
174 | + 'custom_url' => _('Specify the URL to redirect to:'), | |
151 | 175 | } |
152 | 176 | end |
153 | 177 | validates_inclusion_of :redirection_after_login, :in => Environment.login_redirection_options.keys, :allow_nil => true |
... | ... | @@ -172,7 +196,7 @@ class Environment < ActiveRecord::Base |
172 | 196 | acts_as_having_boxes |
173 | 197 | |
174 | 198 | after_create do |env| |
175 | - 3.times do | |
199 | + NUMBER_OF_BOXES.times do | |
176 | 200 | env.boxes << Box.new |
177 | 201 | end |
178 | 202 | |
... | ... | @@ -228,6 +252,9 @@ class Environment < ActiveRecord::Base |
228 | 252 | # store the Environment settings as YAML-serialized Hash. |
229 | 253 | acts_as_having_settings :field => :settings |
230 | 254 | |
255 | + # introduce and explain to users something about the signup | |
256 | + settings_items :signup_intro, :type => String | |
257 | + | |
231 | 258 | # the environment's terms of use: every user must accept them before registering. |
232 | 259 | settings_items :terms_of_use, :type => String |
233 | 260 | |
... | ... | @@ -262,7 +289,20 @@ class Environment < ActiveRecord::Base |
262 | 289 | settings_items :activation_blocked_text, :type => String |
263 | 290 | settings_items :message_for_disabled_enterprise, :type => String, |
264 | 291 | :default => _('This enterprise needs to be enabled.') |
265 | - settings_items :location, :type => String | |
292 | + | |
293 | + settings_items :contact_phone, type: String | |
294 | + settings_items :address, type: String | |
295 | + settings_items :city, type: String | |
296 | + settings_items :state, type: String | |
297 | + settings_items :country_name, type: String | |
298 | + settings_items :lat, type: Float | |
299 | + settings_items :lng, type: Float | |
300 | + settings_items :postal_code, type: String | |
301 | + settings_items :location, type: String | |
302 | + | |
303 | + alias_method :zip_code=, :postal_code | |
304 | + alias_method :zip_code, :postal_code | |
305 | + | |
266 | 306 | settings_items :layout_template, :type => String, :default => 'default' |
267 | 307 | settings_items :homepage, :type => String |
268 | 308 | settings_items :description, :type => String, :default => '<div style="text-align: center"><a href="http://noosfero.org/"><img src="/images/noosfero-network.png" alt="Noosfero"/></a></div>' |
... | ... | @@ -306,6 +346,9 @@ class Environment < ActiveRecord::Base |
306 | 346 | |
307 | 347 | settings_items :signup_welcome_screen_body, :type => String |
308 | 348 | |
349 | + #Captcha settings | |
350 | + settings_items :api_captcha_settings, :type => ActiveSupport::HashWithIndifferentAccess, :default => {} | |
351 | + | |
309 | 352 | def has_custom_welcome_screen? |
310 | 353 | settings[:signup_welcome_screen_body].present? |
311 | 354 | end |
... | ... | @@ -337,6 +380,16 @@ class Environment < ActiveRecord::Base |
337 | 380 | self.save! |
338 | 381 | end |
339 | 382 | |
383 | + def enable_all_plugins | |
384 | + Noosfero::Plugin.available_plugin_names.each do |plugin| | |
385 | + plugin_name = plugin.to_s + "Plugin" | |
386 | + unless self.enabled_plugins.include?(plugin_name) | |
387 | + self.enabled_plugins += [plugin_name] | |
388 | + end | |
389 | + end | |
390 | + self.save! | |
391 | + end | |
392 | + | |
340 | 393 | # Disables a feature identified by its name |
341 | 394 | def disable(feature, must_save=true) |
342 | 395 | self.settings["#{feature}_enabled".to_sym] = false |
... | ... | @@ -439,7 +492,8 @@ class Environment < ActiveRecord::Base |
439 | 492 | end |
440 | 493 | |
441 | 494 | def custom_person_fields |
442 | - self.settings[:custom_person_fields].nil? ? {} : self.settings[:custom_person_fields] | |
495 | + self.settings[:custom_person_fields] = {} if self.settings[:custom_person_fields].nil? | |
496 | + self.settings[:custom_person_fields] | |
443 | 497 | end |
444 | 498 | |
445 | 499 | def custom_person_fields=(values) |
... | ... | @@ -737,8 +791,8 @@ class Environment < ActiveRecord::Base |
737 | 791 | end |
738 | 792 | |
739 | 793 | def is_default_template?(template) |
740 | - is_default = template == community_default_template | |
741 | - is_default = is_default || template == person_default_template | |
794 | + is_default = template == community_default_template | |
795 | + is_default = is_default || template == person_default_template | |
742 | 796 | is_default = is_default || template == enterprise_default_template |
743 | 797 | is_default |
744 | 798 | end |
... | ... | @@ -952,6 +1006,10 @@ class Environment < ActiveRecord::Base |
952 | 1006 | self.licenses.any? |
953 | 1007 | end |
954 | 1008 | |
1009 | + def to_liquid | |
1010 | + HashWithIndifferentAccess.new :name => name | |
1011 | + end | |
1012 | + | |
955 | 1013 | private |
956 | 1014 | |
957 | 1015 | def default_language_available | ... | ... |
app/models/event.rb
... | ... | @@ -3,13 +3,14 @@ require 'builder' |
3 | 3 | |
4 | 4 | class Event < Article |
5 | 5 | |
6 | - attr_accessible :start_date, :end_date, :link, :address | |
6 | + attr_accessible :start_date, :end_date, :link, :address, :presenter | |
7 | 7 | |
8 | 8 | def self.type_name |
9 | 9 | _('Event') |
10 | 10 | end |
11 | 11 | |
12 | 12 | settings_items :address, :type => :string |
13 | + settings_items :presenter, :type => :string | |
13 | 14 | |
14 | 15 | def link=(value) |
15 | 16 | self.setting[:link] = maybe_add_http(value) |
... | ... | @@ -23,7 +24,7 @@ class Event < Article |
23 | 24 | |
24 | 25 | def initialize(*args) |
25 | 26 | super(*args) |
26 | - self.start_date ||= Date.today | |
27 | + self.start_date ||= DateTime.now | |
27 | 28 | end |
28 | 29 | |
29 | 30 | validates_presence_of :title, :start_date |
... | ... | @@ -35,7 +36,7 @@ class Event < Article |
35 | 36 | end |
36 | 37 | |
37 | 38 | scope :by_day, lambda { |date| |
38 | - { :conditions => ['start_date = :date AND end_date IS NULL OR (start_date <= :date AND end_date >= :date)', {:date => date}], | |
39 | + { :conditions => [' start_date >= :start_date AND start_date <= :end_date AND end_date IS NULL OR (start_date <= :end_date AND end_date >= :start_date)', {:start_date => date.beginning_of_day, :end_date => date.end_of_day}], | |
39 | 40 | :order => 'start_date ASC' |
40 | 41 | } |
41 | 42 | } |
... | ... | @@ -80,7 +81,7 @@ class Event < Article |
80 | 81 | |
81 | 82 | def self.date_range(year, month) |
82 | 83 | if year.nil? || month.nil? |
83 | - today = Date.today | |
84 | + today = DateTime.now | |
84 | 85 | year = today.year |
85 | 86 | month = today.month |
86 | 87 | else |
... | ... | @@ -88,7 +89,7 @@ class Event < Article |
88 | 89 | month = month.to_i |
89 | 90 | end |
90 | 91 | |
91 | - first_day = Date.new(year, month, 1) | |
92 | + first_day = DateTime.new(year, month, 1) | |
92 | 93 | last_day = first_day + 1.month - 1.day |
93 | 94 | |
94 | 95 | first_day..last_day |
... | ... | @@ -98,51 +99,23 @@ class Event < Article |
98 | 99 | start_date..(end_date||start_date) |
99 | 100 | end |
100 | 101 | |
101 | - # FIXME this shouldn't be needed | |
102 | - include ActionView::Helpers::TagHelper | |
103 | - include ActionView::Helpers::UrlHelper | |
104 | - include DatesHelper | |
102 | + def first_paragraph | |
103 | + paragraphs = Nokogiri::HTML.fragment(self.body).css('p') | |
104 | + paragraphs.empty? ? '' : paragraphs.first.to_html | |
105 | + end | |
105 | 106 | |
106 | 107 | def to_html(options = {}) |
108 | + event = self | |
109 | + format = options[:format] | |
107 | 110 | |
108 | - result = '' | |
109 | - html = ::Builder::XmlMarkup.new(:target => result) | |
110 | - | |
111 | - html.div(:class => 'event-info' ) { | |
112 | - html.ul(:class => 'event-data' ) { | |
113 | - html.li(:class => 'event-dates' ) { | |
114 | - html.span _('When:') | |
115 | - html.text! show_period(start_date, end_date) | |
116 | - } if start_date.present? || end_date.present? | |
117 | - html.li { | |
118 | - html.span _('URL:') | |
119 | - html.a(self.link || "", 'href' => self.link || "") | |
120 | - } if self.link.present? | |
121 | - html.li { | |
122 | - html.span _('Address:') | |
123 | - html.text! self.address || "" | |
124 | - } if self.address.present? | |
125 | - } | |
126 | - | |
127 | - # TODO: some good soul, please clean this ugly hack: | |
128 | - if self.body | |
129 | - html.div('_____XXXX_DESCRIPTION_GOES_HERE_XXXX_____', :class => 'event-description') | |
130 | - end | |
131 | - } | |
132 | - | |
133 | - if self.body | |
134 | - if options[:format] == 'short' | |
135 | - result.sub!('_____XXXX_DESCRIPTION_GOES_HERE_XXXX_____', display_short_format(self)) | |
136 | - else | |
137 | - result.sub!('_____XXXX_DESCRIPTION_GOES_HERE_XXXX_____', self.body) | |
138 | - end | |
111 | + proc do | |
112 | + render :file => 'content_viewer/event_page', :locals => { :event => event, | |
113 | + :format => format } | |
139 | 114 | end |
140 | - | |
141 | - result | |
142 | 115 | end |
143 | 116 | |
144 | 117 | def duration |
145 | - ((self.end_date || self.start_date) - self.start_date).to_i | |
118 | + (((self.end_date || self.start_date) - self.start_date).to_i/60/60/24) | |
146 | 119 | end |
147 | 120 | |
148 | 121 | alias_method :article_lead, :lead |
... | ... | @@ -162,6 +135,10 @@ class Event < Article |
162 | 135 | true |
163 | 136 | end |
164 | 137 | |
138 | + def can_display_media_panel? | |
139 | + true | |
140 | + end | |
141 | + | |
165 | 142 | include Noosfero::TranslatableContent |
166 | 143 | include MaybeAddHttp |
167 | 144 | ... | ... |
app/models/favorite_enterprise_person.rb
1 | 1 | class FavoriteEnterprisePerson < ActiveRecord::Base |
2 | 2 | |
3 | - self.table_name = :favorite_enteprises_people | |
3 | + attr_accessible :person, :enterprise | |
4 | + | |
5 | + track_actions :favorite_enterprise, :after_create, keep_params: [:enterprise_name, :enterprise_url], if: proc{ |f| f.is_trackable? } | |
4 | 6 | |
5 | 7 | belongs_to :enterprise |
6 | 8 | belongs_to :person |
7 | 9 | |
10 | + protected | |
11 | + | |
12 | + def is_trackable? | |
13 | + self.enterprise.public? | |
14 | + end | |
15 | + | |
16 | + def enterprise_name | |
17 | + self.enterprise.short_name(nil) | |
18 | + end | |
19 | + def enterprise_url | |
20 | + self.enterprise.url | |
21 | + end | |
22 | + | |
8 | 23 | end | ... | ... |
app/models/featured_products_block.rb
app/models/feed_reader_block.rb
... | ... | @@ -40,6 +40,10 @@ class FeedReaderBlock < Block |
40 | 40 | _('Feed reader') |
41 | 41 | end |
42 | 42 | |
43 | + def self.pretty_name | |
44 | + _('Feed Reader') | |
45 | + end | |
46 | + | |
43 | 47 | def help |
44 | 48 | _('This block can be used to list the latest new from any site you want. You just need to inform the address of a RSS feed.') |
45 | 49 | end | ... | ... |
app/models/forum.rb
... | ... | @@ -3,11 +3,11 @@ class Forum < Folder |
3 | 3 | acts_as_having_posts :order => 'updated_at DESC' |
4 | 4 | include PostsLimit |
5 | 5 | |
6 | - attr_accessible :has_terms_of_use, :terms_of_use, :allows_members_to_create_topics | |
6 | + attr_accessible :has_terms_of_use, :terms_of_use, :topic_creation | |
7 | 7 | |
8 | 8 | settings_items :terms_of_use, :type => :string, :default => "" |
9 | 9 | settings_items :has_terms_of_use, :type => :boolean, :default => false |
10 | - settings_items :allows_members_to_create_topics, :type => :boolean, :default => false | |
10 | + settings_items :topic_creation, :type => :string, :default => 'self' | |
11 | 11 | has_and_belongs_to_many :users_with_agreement, :class_name => 'Person', :join_table => 'terms_forum_people' |
12 | 12 | |
13 | 13 | before_save do |forum| |
... | ... | @@ -33,6 +33,23 @@ class Forum < Folder |
33 | 33 | _('An internet forum, also called message board, where discussions can be held.') |
34 | 34 | end |
35 | 35 | |
36 | + module TopicCreation | |
37 | + BASE = ActiveSupport::OrderedHash.new | |
38 | + BASE['users'] = _('Logged users') | |
39 | + | |
40 | + PERSON = ActiveSupport::OrderedHash.new | |
41 | + PERSON['self'] = _('Me') | |
42 | + PERSON['related'] = _('Friends') | |
43 | + | |
44 | + GROUP = ActiveSupport::OrderedHash.new | |
45 | + GROUP['self'] = _('Administrators') | |
46 | + GROUP['related'] = _('Members') | |
47 | + | |
48 | + def self.general_options(forum) | |
49 | + forum.profile.person? ? PERSON.merge(BASE) : GROUP.merge(BASE) | |
50 | + end | |
51 | + end | |
52 | + | |
36 | 53 | include ActionView::Helpers::TagHelper |
37 | 54 | def to_html(options = {}) |
38 | 55 | proc do |
... | ... | @@ -69,11 +86,17 @@ class Forum < Folder |
69 | 86 | self.users_with_agreement.exists? user |
70 | 87 | end |
71 | 88 | |
72 | - def can_create_topic?(user, profile) | |
73 | - return profile.community? && profile.members.include?(user) && self.allows_members_to_create_topics | |
89 | + def can_create_topic?(user) | |
90 | + return true if user == profile || profile.admins.include?(user) || profile.environment.admins.include?(user) | |
91 | + case topic_creation | |
92 | + when 'related' | |
93 | + profile.person? ? profile.friends.include?(user) : profile.members.include?(user) | |
94 | + when 'users' | |
95 | + user.present? | |
96 | + end | |
74 | 97 | end |
75 | 98 | |
76 | 99 | def allow_create?(user) |
77 | - super || can_create_topic?(user, profile) | |
100 | + super || can_create_topic?(user) | |
78 | 101 | end |
79 | 102 | end | ... | ... |
app/models/highlights_block.rb
... | ... | @@ -12,6 +12,7 @@ class HighlightsBlock < Block |
12 | 12 | block.images.each do |i| |
13 | 13 | i[:image_id] = i[:image_id].to_i |
14 | 14 | i[:position] = i[:position].to_i |
15 | + i[:address] = Noosfero.root + i[:address] unless Noosfero.root.nil? | |
15 | 16 | begin |
16 | 17 | file = UploadedFile.find(i[:image_id]) |
17 | 18 | i[:image_src] = file.public_filename |
... | ... | @@ -22,12 +23,20 @@ class HighlightsBlock < Block |
22 | 23 | end |
23 | 24 | |
24 | 25 | def self.description |
25 | - _('Highlights') | |
26 | + _('Creates image slideshow') | |
26 | 27 | end |
27 | 28 | |
28 | 29 | def featured_images |
29 | - block_images = images.select{|i| !i[:image_src].nil? }.sort { |x, y| x[:position] <=> y[:position] } | |
30 | - shuffle ? block_images.shuffle : block_images | |
30 | + images = get_images | |
31 | + shuffle ? images.shuffle : images | |
32 | + end | |
33 | + | |
34 | + def get_images | |
35 | + images.select do |i| | |
36 | + !i[:image_src].nil? | |
37 | + end.sort do |x, y| | |
38 | + x[:position] <=> y[:position] | |
39 | + end | |
31 | 40 | end |
32 | 41 | |
33 | 42 | def content(args={}) | ... | ... |
app/models/image.rb
app/models/invitation.rb
... | ... | @@ -6,6 +6,8 @@ class Invitation < Task |
6 | 6 | |
7 | 7 | validates_presence_of :target_id, :if => Proc.new{|invite| invite.friend_email.blank?} |
8 | 8 | |
9 | + validates :requestor, kind_of: {kind: Person} | |
10 | + | |
9 | 11 | validates_presence_of :friend_email, :if => Proc.new{|invite| invite.target_id.blank?} |
10 | 12 | validates_format_of :friend_email, :with => Noosfero::Constants::EMAIL_FORMAT, :if => Proc.new{|invite| invite.target_id.blank?} |
11 | 13 | |
... | ... | @@ -34,7 +36,7 @@ class Invitation < Task |
34 | 36 | end |
35 | 37 | |
36 | 38 | def not_invite_yourself |
37 | - email = friend ? friend.user.email : friend_email | |
39 | + email = friend && friend.person? ? friend.user.email : friend_email | |
38 | 40 | if person && email && person.user.email == email |
39 | 41 | self.errors.add(:base, _("You can't invite youself")) |
40 | 42 | end |
... | ... | @@ -136,7 +138,11 @@ class Invitation < Task |
136 | 138 | end |
137 | 139 | |
138 | 140 | def environment |
139 | - self.requestor.environment | |
141 | + if self.requestor | |
142 | + self.requestor.environment | |
143 | + else | |
144 | + nil | |
145 | + end | |
140 | 146 | end |
141 | 147 | |
142 | 148 | end | ... | ... |
app/models/link_list_block.rb
... | ... | @@ -55,6 +55,10 @@ class LinkListBlock < Block |
55 | 55 | _('This block can be used to create a menu of links. You can add, remove and update the links as you wish.') |
56 | 56 | end |
57 | 57 | |
58 | + def self.pretty_name | |
59 | + _('Link list') | |
60 | + end | |
61 | + | |
58 | 62 | def content(args={}) |
59 | 63 | block_title(title) + |
60 | 64 | content_tag('ul', | ... | ... |