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', | ... | ... |