Commit 2b942cdfed60a2df7dcc906b18ab495c55d2666f

Authored by Ábner Silva de Oliveira
2 parents ef5a4c0a e5ecf4b1

merge with noosfero api branch

Showing 190 changed files with 10340 additions and 8390 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 190 files displayed.

.gitlab-ci.yml 0 → 100644
@@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
  1 +before_script:
  2 + - mkdir -p tmp/pids log
  3 + - script/noosfero-plugins disableall
  4 + - bundle check || bundle install
  5 +# database
  6 + - cp config/database.yml.gitlab-ci config/database.yml
  7 + - createdb gitlab_ci_test || true
  8 + - bundle exec rake db:schema:load
  9 + - bundle exec rake db:migrate
  10 +
  11 +units:
  12 + script: 'bundle exec rake test:units'
  13 +functionals:
  14 + script: 'bundle exec rake test:functionals'
  15 +integration:
  16 + script: 'bundle exec rake test:integration'
  17 +cucumber:
  18 + script: 'bundle exec rake cucumber'
  19 +selenium:
  20 + script: 'bundle exec rake selenium'
  21 +plugins:
  22 + script: 'bundle exec rake test:noosfero_plugins'
  23 +
.travis.yml 0 → 100644
@@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
  1 +language: ruby
  2 +rvm:
  3 +# for 2.2 support we need to upgrade the pg gem
  4 + - 2.1.6
  5 +
  6 +before_install:
  7 +# dependencies
  8 + - sudo apt-get update
  9 + - sudo apt-get -y install po4a iso-codes tango-icon-theme pidgin-data openjdk-6-jre curl wget
  10 + - sudo apt-get -y install libmagickwand-dev libpq-dev libreadline-dev libsqlite3-dev libxslt1-dev
  11 +# selenium support
  12 + - export DISPLAY=:99.0
  13 + - sh -e /etc/init.d/xvfb start
  14 +
  15 +before_script:
  16 + - mkdir -p tmp/pids log
  17 + - script/noosfero-plugins disableall
  18 + - bundle check || bundle install
  19 +# database
  20 + - cp config/database.yml.travis config/database.yml
  21 + - psql -c 'create database myapp_test;' -U postgres
  22 + - bundle exec rake db:schema:load
  23 + - bundle exec rake db:migrate
  24 +
  25 +env:
  26 + - TASK=test:units
  27 + - TASK=test:functionals
  28 + - TASK=test:integration
  29 + - TASK=cucumber
  30 + - TASK=selenium
  31 + - TASK=test:noosfero_plugins
  32 +
  33 +script:
  34 + - bundle exec rake $TASK
  35 +
@@ -6,131 +6,132 @@ noosfero, that's not a problem). @@ -6,131 +6,132 @@ noosfero, that's not a problem).
6 Developers 6 Developers
7 ========== 7 ==========
8 8
9 -Ábner Silva de Oliveira <abner.oliveira@serpro.gov.br>  
10 Alan Freihof Tygel <alantygel@gmail.com> 9 Alan Freihof Tygel <alantygel@gmail.com>
11 -alcampelo <alcampelo@alcampelo.(none)>  
12 -Alessandro Palmeira <alessandro.palmeira@gmail.com>  
13 Alessandro Palmeira + Caio C. Salgado <alessandro.palmeira@gmail.com> 10 Alessandro Palmeira + Caio C. Salgado <alessandro.palmeira@gmail.com>
  11 +Alessandro Palmeira + Caio Salgado + Diego Araújo + João M. M. da Silva <diegoamc90@gmail.com>
14 Alessandro Palmeira + Caio Salgado <alessandro.palmeira@gmail.com> 12 Alessandro Palmeira + Caio Salgado <alessandro.palmeira@gmail.com>
15 Alessandro Palmeira + Caio Salgado <caio.csalgado@gmail.com> 13 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> 14 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> 15 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> 16 +Alessandro Palmeira + Daniel Alves + Diego Araújo <diegoamc90@gmail.com>
  17 +Alessandro Palmeira + Daniel Alves <alessandro.palmeira@gmail.com>
23 Alessandro Palmeira + Diego Araujo + Daniela Feitosa <alessandro.palmeira@gmail.com> 18 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> 19 Alessandro Palmeira + Diego Araujo + Eduardo Morais <alessandro.palmeira@gmail.com>
  20 +Alessandro Palmeira + Diego Araujo + João M. M. da Silva + Paulo Meirelles <alessandro.palmeira@gmail.com>
  21 +Alessandro Palmeira + Diego Araujo + Rafael Manzo <alessandro.palmeira@gmail.com>
  22 +Alessandro Palmeira + Diego Araujo <alessandro.palmeira@gmail.com>
  23 +Alessandro Palmeira + Diego Araujo <diegoamc90@gmail.com>
27 Alessandro Palmeira + Diego Araújo + João M. M. da Silva <alessandro.palmeira@gmail.com> 24 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> 25 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> 26 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> 27 +Alessandro Palmeira + Diego Araújo + Pedro Leal <diegoamc90@gmail.com>
  28 +Alessandro Palmeira + Diego Araújo <alessandro.palmeira@gmail.com>
  29 +Alessandro Palmeira + Diego Araújo <diegoamc90@gmail.com>
33 Alessandro Palmeira + Eduardo Morais <alessandro.palmeira@gmail.com> 30 Alessandro Palmeira + Eduardo Morais <alessandro.palmeira@gmail.com>
34 Alessandro Palmeira + Guilherme Rojas <alessandro.palmeira@gmail.com> 31 Alessandro Palmeira + Guilherme Rojas <alessandro.palmeira@gmail.com>
35 Alessandro Palmeira + Jefferson Fernandes <alessandro.palmeira@gmail.com> 32 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> 33 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> 34 Alessandro Palmeira + João M. M. Silva <alessandro.palmeira@gmail.com>
40 -Alessandro Palmeira + Paulo Meirelles <alessandro.palmeira@gmail.com> 35 +Alessandro Palmeira + João M. M. da Silva + Renan Teruo <alessandro.palmeira@gmail.com>
  36 +Alessandro Palmeira + João M. M. da Silva <alessandro.palmeira@gmail.com>
41 Alessandro Palmeira + Paulo Meirelles + João M. M. da Silva <alessandro.palmeira@gmail.com> 37 Alessandro Palmeira + Paulo Meirelles + João M. M. da Silva <alessandro.palmeira@gmail.com>
  38 +Alessandro Palmeira + Paulo Meirelles <alessandro.palmeira@gmail.com>
42 Alessandro Palmeira + Rafael Manzo <alessandro.palmeira@gmail.com> 39 Alessandro Palmeira + Rafael Manzo <alessandro.palmeira@gmail.com>
43 -analosnak <analosnak@gmail.com> 40 +Alessandro Palmeira <alessandro.palmeira@gmail.com>
44 Ana Losnak <analosnak@gmail.com> 41 Ana Losnak <analosnak@gmail.com>
45 Andre Bernardes <andrebsguedes@gmail.com> 42 Andre Bernardes <andrebsguedes@gmail.com>
  43 +André Bernardes <andrebsguedes@gmail.com>
  44 +André Guedes <andrebsguedes@fedora.local>
  45 +André Guedes <andrebsguedes@gmail.com>
46 Antonio Terceiro + Carlos Morais <terceiro@colivre.coop.br> 46 Antonio Terceiro + Carlos Morais <terceiro@colivre.coop.br>
47 Antonio Terceiro + Paulo Meirelles <terceiro@colivre.coop.br> 47 Antonio Terceiro + Paulo Meirelles <terceiro@colivre.coop.br>
48 Antonio Terceiro <terceiro@colivre.coop.br> 48 Antonio Terceiro <terceiro@colivre.coop.br>
49 Arthur Del Esposte <arthurmde@gmail.com> 49 Arthur Del Esposte <arthurmde@gmail.com>
50 Arthur Del Esposte <arthurmde@yahoo.com.br> 50 Arthur Del Esposte <arthurmde@yahoo.com.br>
  51 +Athos Ribeiro <athoscribeiro@gmail.com>
51 Aurelio A. Heckert <aurelio@colivre.coop.br> 52 Aurelio A. Heckert <aurelio@colivre.coop.br>
  53 +Braulio Bhavamitra <braulio@eita.org.br>
52 Braulio Bhavamitra <brauliobo@gmail.com> 54 Braulio Bhavamitra <brauliobo@gmail.com>
53 Bráulio Bhavamitra <brauliobo@gmail.com> 55 Bráulio Bhavamitra <brauliobo@gmail.com>
54 -Braulio Bhavamitra <braulio@eita.org.br>  
55 -Caio <caio.csalgado@gmail.com>  
56 Caio + Diego + Pedro + João <caio.csalgado@gmail.com> 56 Caio + Diego + Pedro + João <caio.csalgado@gmail.com>
  57 +Caio <caio.csalgado@gmail.com>
57 Caio Formiga <caio.formiga@gmail.com> 58 Caio Formiga <caio.formiga@gmail.com>
58 -Caio, Pedro <caio.csalgado@gmail.com> 59 +Caio SBA <caio@colivre.coop.br>
59 Caio Salgado + Alessandro Palmeira <caio.csalgado@gmail.com> 60 Caio Salgado + Alessandro Palmeira <caio.csalgado@gmail.com>
60 -Caio Salgado <caio.csalgado@gmail.com>  
61 Caio Salgado + Carlos Morais + Diego Araújo + Pedro Leal <diegoamc90@gmail.com> 61 Caio Salgado + Carlos Morais + Diego Araújo + Pedro Leal <diegoamc90@gmail.com>
62 Caio Salgado + Diego Araujo <caio.csalgado@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> 63 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> 64 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> 65 Caio Salgado + Diego Araújo + Pedro Leal <caio.csalgado@gmail.com>
68 Caio Salgado + Diego Araújo + Pedro Leal <diegoamc90@gmail.com> 66 Caio Salgado + Diego Araújo + Pedro Leal <diegoamc90@gmail.com>
69 Caio Salgado + Diego Araújo + Rafael Manzo <diegoamc90@gmail.com> 67 Caio Salgado + Diego Araújo + Rafael Manzo <diegoamc90@gmail.com>
  68 +Caio Salgado + Diego Araújo <caio.csalgado@gmail.com>
  69 +Caio Salgado + Diego Araújo <diegoamc90@gmail.com>
70 Caio Salgado + Jefferson Fernandes <caio.csalgado@gmail.com> 70 Caio Salgado + Jefferson Fernandes <caio.csalgado@gmail.com>
71 Caio Salgado + Jefferson Fernandes <jeffs.fernandes@gmail.com> 71 Caio Salgado + Jefferson Fernandes <jeffs.fernandes@gmail.com>
72 Caio Salgado + Rafael Manzo <caio.csalgado@gmail.com> 72 Caio Salgado + Rafael Manzo <caio.csalgado@gmail.com>
  73 +Caio Salgado + Renan Teruo + Jefferson Fernandes <jeffs.fernandes@gmail.com>
73 Caio Salgado + Renan Teruo <caio.csalgado@gmail.com> 74 Caio Salgado + Renan Teruo <caio.csalgado@gmail.com>
74 Caio Salgado + Renan Teruo <caio.salgado@gmail.com> 75 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> 76 Caio Salgado + Renan Teruo <renanteruoc@gmail.com>
77 -Caio SBA <caio@colivre.coop.br> 77 +Caio Salgado <caio.csalgado@gmail.com>
78 Caio Tiago Oliveira <caiotiago@colivre.coop.br> 78 Caio Tiago Oliveira <caiotiago@colivre.coop.br>
  79 +Caio, Pedro <caio.csalgado@gmail.com>
79 Carlos Andre de Souza <carlos.andre.souza@msn.com> 80 Carlos Andre de Souza <carlos.andre.souza@msn.com>
80 -Carlos Morais <carlos88morais@gmail.com>  
81 Carlos Morais + Diego Araújo <diegoamc90@gmail.com> 81 Carlos Morais + Diego Araújo <diegoamc90@gmail.com>
82 Carlos Morais + Eduardo Morais <carlos88morais@gmail.com> 82 Carlos Morais + Eduardo Morais <carlos88morais@gmail.com>
83 Carlos Morais + Paulo Meirelles <carlos88morais@gmail.com> 83 Carlos Morais + Paulo Meirelles <carlos88morais@gmail.com>
84 Carlos Morais + Pedro Leal <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> 85 +Carlos Morais <carlos88morais@gmail.com>
87 Daniel Alves + Diego Araújo + Guilherme Rojas <danpaulalves@gmail.com> 86 Daniel Alves + Diego Araújo + Guilherme Rojas <danpaulalves@gmail.com>
88 Daniel Alves + Diego Araújo + Guilherme Rojas <diegoamc90@gmail.com> 87 Daniel Alves + Diego Araújo + Guilherme Rojas <diegoamc90@gmail.com>
89 Daniel Alves + Diego Araújo + Guilherme Rojas <guilhermehrojas@gmail.com> 88 Daniel Alves + Diego Araújo + Guilherme Rojas <guilhermehrojas@gmail.com>
  89 +Daniel Alves + Diego Araújo <danpaulalves@gmail.com>
  90 +Daniel Alves + Diego Araújo <diegoamc90@gmail.com>
90 Daniel Alves + Guilherme Rojas <danpaulalves@gmail.com> 91 Daniel Alves + Guilherme Rojas <danpaulalves@gmail.com>
91 Daniel Alves + Rafael Manzo <rr.manzo@gmail.com> 92 Daniel Alves + Rafael Manzo <rr.manzo@gmail.com>
92 -Daniela Soares Feitosa <danielafeitosa@colivre.coop.br>  
93 Daniel Bucher <daniel.bucher88@gmail.com> 93 Daniel Bucher <daniel.bucher88@gmail.com>
94 Daniel Cunha <daniel@colivre.coop.br> 94 Daniel Cunha <daniel@colivre.coop.br>
95 -daniel <dtygel@eita.org.br> 95 +Daniela Soares Feitosa <danielafeitosa@colivre.coop.br>
96 David Carlos <ddavidcarlos1392@gmail.com> 96 David Carlos <ddavidcarlos1392@gmail.com>
97 -diegoamc <diegoamc90@gmail.com>  
98 -Diego Araújo + Alessandro Palmeira <diegoamc90@gmail.com> 97 +Diego + Jefferson <diegoamc90@gmail.com>
  98 +Diego + Renan <renanteruoc@gmail.com>
  99 +Diego Araujo + Caio Salgado <diegoamc90@gmail.com>
  100 +Diego Araujo + Jefferson Fernandes <jeffs.fernandes@gmail.com>
  101 +Diego Araujo + Rafael Manzo <diegoamc90@gmail.com>
  102 +Diego Araujo + Rodrigo Souto + Rafael Manzo <rr.manzo@gmail.com>
99 Diego Araújo + Alessandro Palmeira + João M. M. da Silva <diegoamc90@gmail.com> 103 Diego Araújo + Alessandro Palmeira + João M. M. da Silva <diegoamc90@gmail.com>
100 Diego Araújo + Alessandro Palmeira + Rafael Manzo <rr.manzo@gmail.com> 104 Diego Araújo + Alessandro Palmeira + Rafael Manzo <rr.manzo@gmail.com>
101 -Diego Araujo + Caio Salgado <diegoamc90@gmail.com> 105 +Diego Araújo + Alessandro Palmeira <diegoamc90@gmail.com>
102 Diego Araújo + Daniel Alves + Rafael Manzo <rr.manzo@gmail.com> 106 Diego Araújo + Daniel Alves + Rafael Manzo <rr.manzo@gmail.com>
103 -Diego Araújo <diegoamc90@gmail.com>  
104 Diego Araújo + Eduardo Morais + Paulo Meirelles <diegoamc90@gmail.com> 107 Diego Araújo + Eduardo Morais + Paulo Meirelles <diegoamc90@gmail.com>
105 Diego Araújo + Guilherme Rojas <diegoamc90@gmail.com> 108 Diego Araújo + Guilherme Rojas <diegoamc90@gmail.com>
106 Diego Araújo + Jefferson Fernandes <diegoamc90@gmail.com> 109 Diego Araújo + Jefferson Fernandes <diegoamc90@gmail.com>
107 -Diego Araujo + Jefferson Fernandes <jeffs.fernandes@gmail.com>  
108 -Diego Araújo + João Machini <diegoamc90@gmail.com>  
109 -Diego Araújo + João Machini <digoamc90@gmail.com>  
110 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 + Alessandro Palmeira <jaodsilv@linux.ime.usp.br>
111 -Diego Araújo + João M. M. da Silva <diegoamc90@gmail.com>  
112 Diego Araújo + João M. M. da Silva + João Machini <diegoamc90@gmail.com> 111 Diego Araújo + João M. M. da Silva + João Machini <diegoamc90@gmail.com>
113 Diego Araújo + João M. M. da Silva + Pedro Leal <diegoamc90@gmail.com> 112 Diego Araújo + João M. M. da Silva + Pedro Leal <diegoamc90@gmail.com>
  113 +Diego Araújo + João M. M. da Silva <diegoamc90@gmail.com>
  114 +Diego Araújo + João Machini <diegoamc90@gmail.com>
  115 +Diego Araújo + João Machini <digoamc90@gmail.com>
114 Diego Araújo + Paulo Meirelles <diegoamc90@gmail.com> 116 Diego Araújo + Paulo Meirelles <diegoamc90@gmail.com>
115 Diego Araújo + Pedro Leal <diegoamc90@gmail.com> 117 Diego Araújo + Pedro Leal <diegoamc90@gmail.com>
116 -Diego Araujo + Rafael Manzo <diegoamc90@gmail.com>  
117 Diego Araújo + Rafael Manzo <diegoamc90@gmail.com> 118 Diego Araújo + Rafael Manzo <diegoamc90@gmail.com>
118 Diego Araújo + Renan Teruo + Alessandro Palmeira <diegoamc90@gmail.com> 119 Diego Araújo + Renan Teruo + Alessandro Palmeira <diegoamc90@gmail.com>
119 Diego Araújo + Renan Teruo <diegoamc90@gmail.com> 120 Diego Araújo + Renan Teruo <diegoamc90@gmail.com>
120 -Diego Araujo + Rodrigo Souto + Rafael Manzo <rr.manzo@gmail.com>  
121 -Diego + Jefferson <diegoamc90@gmail.com> 121 +Diego Araújo <diegoamc90@gmail.com>
122 Diego Martinez <diegoamc90@gmail.com> 122 Diego Martinez <diegoamc90@gmail.com>
123 -Diego + Renan <renanteruoc@gmail.com>  
124 -dtygel <dtygel@gmail.com>  
125 DylanGuedes <djmgguedes@gmail.com> 123 DylanGuedes <djmgguedes@gmail.com>
126 Eduardo Passos <eduardo@risa.localdomain.localhost> 124 Eduardo Passos <eduardo@risa.localdomain.localhost>
127 Eduardo Passos <eduardosteps@gmail.com> 125 Eduardo Passos <eduardosteps@gmail.com>
128 Eduardo Tourinho Edington <eduardo.edington@serpro.gov.br> 126 Eduardo Tourinho Edington <eduardo.edington@serpro.gov.br>
  127 +Eduardo Vital <vitaldu@gmail.com>
129 Evandro Jr <evandrojr@gmail.com> 128 Evandro Jr <evandrojr@gmail.com>
130 Evandro Junior <evandrojr@gmail.com> 129 Evandro Junior <evandrojr@gmail.com>
131 -Fabio Teixeira <fabio1079@gmail.com> 130 +Evandro Magalhaes Leite Junior <evandro.leite@serpro.gov.br>
132 FAMMA TV NOTICIAS MEDIOS DE CO <revistafammatvmusic.oficial@gmail.com> 131 FAMMA TV NOTICIAS MEDIOS DE CO <revistafammatvmusic.oficial@gmail.com>
  132 +Fabio Teixeira <fabio1079@gmail.com>
133 Fernanda Lopes <nanda.listas+psl@gmail.com> 133 Fernanda Lopes <nanda.listas+psl@gmail.com>
  134 +Filipe Ribeiro <firibeiro77@live.com>
134 Francisco Marcelo A. Lima Júnior <francisco.lima-junior@serpro.gov.br> 135 Francisco Marcelo A. Lima Júnior <francisco.lima-junior@serpro.gov.br>
135 Francisco Marcelo de Araujo Lima Junior <79350259591@serpro-1457614.(none)> 136 Francisco Marcelo de Araujo Lima Junior <79350259591@serpro-1457614.(none)>
136 Francisco Marcelo de Araújo Lima Júnior <francisco.lima-junior@serpro.gov.br> 137 Francisco Marcelo de Araújo Lima Júnior <francisco.lima-junior@serpro.gov.br>
@@ -144,25 +145,29 @@ Hugo Melo &lt;hugo@riseup.net&gt; @@ -144,25 +145,29 @@ Hugo Melo &lt;hugo@riseup.net&gt;
144 Isaac Canan <isaac@intelletto.com.br> 145 Isaac Canan <isaac@intelletto.com.br>
145 Italo Valcy <italo@dcc.ufba.br> 146 Italo Valcy <italo@dcc.ufba.br>
146 Jefferson Fernandes + Diego Araujo + Rafael Manzo <jeffs.fernandes@gmail.com> 147 Jefferson Fernandes + Diego Araujo + Rafael Manzo <jeffs.fernandes@gmail.com>
147 -Jefferson Fernandes + Joao M. M. da Silva <jeffs.fernandes@gmail.com>  
148 Jefferson Fernandes + Joao M. M. Silva <jeffs.fernandes@gmail.com> 148 Jefferson Fernandes + Joao M. M. Silva <jeffs.fernandes@gmail.com>
149 -Jérôme Jutteau <j.jutteau@gmail.com>  
150 -João da Silva + Eduardo Morais + Rafael Manzo <rr.manzo@gmail.com>  
151 -João da Silva <jaodsilv@linux.ime.usp.br>  
152 -João Marco Maciel da Silva + Rafael Manzo + Renan Teruo <jaodsilv@linux.ime.usp.br> 149 +Jefferson Fernandes + Joao M. M. da Silva <jeffs.fernandes@gmail.com>
  150 +Joao M. M. Silva + Jefferson Fernandes <jaodsilv@linux.ime.usp.br>
  151 +Joao M. M. da Silva + Alessandro Palmeira <jaodsilv@linux.ime.usp.br>
  152 +Joao M. M. da Silva + Jefferson Fernandes <jaodsilv@linux.ime.usp.br>
  153 +Joenio Costa <joenio@colivre.coop.br>
  154 +Jose Pedro <1jpsneto@gmail.com>
  155 +Josef Spillner <josef.spillner@tu-dresden.de>
  156 +João M. M. Silva + Caio Salgado <jaodsilv@linux.ime.usp.br>
  157 +João M. M. Silva + Diego Araújo <jaodsilv@linux.ime.usp.br>
  158 +João M. M. Silva + Paulo Meirelles <jaodsilv@linux.ime.usp.br>
  159 +João M. M. Silva + Rafael Manzo <jaodsilv@linux.ime.usp.br>
  160 +João M. M. Silva + Renan Teruo <jaodsilv@linux.ime.usp.br>
153 João M. M. da Silva + Alessandro Palmeira + Diego Araújo + Caio Salgado <jaodsilv@linux.ime.usp.br> 161 João M. M. da Silva + Alessandro Palmeira + Diego Araújo + Caio Salgado <jaodsilv@linux.ime.usp.br>
154 João M. M. da Silva + Alessandro Palmeira + Diego Araújo <jaodsilv@linux.ime.usp.br> 162 João M. M. da Silva + Alessandro Palmeira + Diego Araújo <jaodsilv@linux.ime.usp.br>
155 -Joao M. M. da Silva + Alessandro Palmeira <jaodsilv@linux.ime.usp.br>  
156 -João M. M. da Silva + Alessandro Palmeira <jaodsilv@linux.ime.usp.br>  
157 João M. M. da Silva + Alessandro Palmeira + João Machini <jaodsilv@linux.ime.usp.br> 163 João M. M. da Silva + Alessandro Palmeira + João Machini <jaodsilv@linux.ime.usp.br>
  164 +João M. M. da Silva + Alessandro Palmeira <jaodsilv@linux.ime.usp.br>
158 João M. M. da Silva + Caio Salgado + Alessandro Palmeira <jaodsilv@linux.ime.usp.br> 165 João M. M. da Silva + Caio Salgado + Alessandro Palmeira <jaodsilv@linux.ime.usp.br>
159 João M. M. da Silva + Caio Salgado <jaodsilv@linux.ime.usp.br> 166 João M. M. da Silva + Caio Salgado <jaodsilv@linux.ime.usp.br>
160 João M. M. da Silva + Carlos Morais <jaodsilv@linux.ime.usp.br> 167 João M. M. da Silva + Carlos Morais <jaodsilv@linux.ime.usp.br>
  168 +João M. M. da Silva + Diego Araújo + Pedro Leal <jaodsilv@linux.ime.usp.br>
161 João M. M. da Silva + Diego Araújo <diegoamc90@gmail.com> 169 João M. M. da Silva + Diego Araújo <diegoamc90@gmail.com>
162 João M. M. da Silva + Diego Araújo <jaodsilv@linux.ime.usp.br> 170 João M. M. da Silva + Diego Araújo <jaodsilv@linux.ime.usp.br>
163 -João M. M. da Silva + Diego Araújo + Pedro Leal <jaodsilv@linux.ime.usp.br>  
164 -João M. M. da Silva <jaodsilv@linux.ime.usp.br>  
165 -Joao M. M. da Silva + Jefferson Fernandes <jaodsilv@linux.ime.usp.br>  
166 João M. M. da Silva + Jefferson Fernandes <jaodsilv@linux.ime.usp.br> 171 João M. M. da Silva + Jefferson Fernandes <jaodsilv@linux.ime.usp.br>
167 João M. M. da Silva + João M. Miranda <jaodsilv@linux.ime.usp.br> 172 João M. M. da Silva + João M. Miranda <jaodsilv@linux.ime.usp.br>
168 João M. M. da Silva + Paulo Meirelles <jaodsilv@linux.ime.usp.br> 173 João M. M. da Silva + Paulo Meirelles <jaodsilv@linux.ime.usp.br>
@@ -170,46 +175,44 @@ João M. M. da Silva + Pedro Leal &lt;jaodsilv@linux.ime.usp.br&gt; @@ -170,46 +175,44 @@ João M. M. da Silva + Pedro Leal &lt;jaodsilv@linux.ime.usp.br&gt;
170 João M. M. da Silva + Rafael Manzo + Diego Araújo <jaodsilv@linux.ime.usp.br> 175 João M. M. da Silva + Rafael Manzo + Diego Araújo <jaodsilv@linux.ime.usp.br>
171 João M. M. da Silva + Rafael Manzo <jaodsilv@linux.ime.usp.br> 176 João M. M. da Silva + Rafael Manzo <jaodsilv@linux.ime.usp.br>
172 João M. M. da Silva + Renan Teruo <jaodsilv@linux.ime.usp.br> 177 João M. M. da Silva + Renan Teruo <jaodsilv@linux.ime.usp.br>
173 -João M. M. Silva + Caio Salgado <jaodsilv@linux.ime.usp.br>  
174 -João M. M. Silva + Diego Araújo <jaodsilv@linux.ime.usp.br>  
175 -Joao M. M. Silva + Jefferson Fernandes <jaodsilv@linux.ime.usp.br>  
176 -João M. M. Silva + Paulo Meirelles <jaodsilv@linux.ime.usp.br>  
177 -João M. M. Silva + Rafael Manzo <jaodsilv@linux.ime.usp.br>  
178 -João M. M. Silva + Renan Teruo <jaodsilv@linux.ime.usp.br>  
179 -Joenio Costa <joenio@colivre.coop.br>  
180 -Josef Spillner <josef.spillner@tu-dresden.de>  
181 -Jose Pedro <1jpsneto@gmail.com> 178 +João M. M. da Silva <jaodsilv@linux.ime.usp.br>
  179 +João Marco Maciel da Silva + Rafael Manzo + Renan Teruo <jaodsilv@linux.ime.usp.br>
  180 +João da Silva + Eduardo Morais + Rafael Manzo <rr.manzo@gmail.com>
  181 +João da Silva <jaodsilv@linux.ime.usp.br>
182 Junior Silva <junior@bajor.localhost.localdomain> 182 Junior Silva <junior@bajor.localhost.localdomain>
183 Junior Silva <junior@sedeantigo.colivre.coop.br> 183 Junior Silva <junior@sedeantigo.colivre.coop.br>
184 Junior Silva <juniorsilva1001@gmail.com> 184 Junior Silva <juniorsilva1001@gmail.com>
185 Junior Silva <juniorsilva7@juniorsilva-Aspire-5750Z.(none)> 185 Junior Silva <juniorsilva7@juniorsilva-Aspire-5750Z.(none)>
186 Junior Silva <juniorsilva@colivre.coop.br> 186 Junior Silva <juniorsilva@colivre.coop.br>
187 -juniorsilva <juniorsilva@QonoS.localhost.localdomain> 187 +Jérôme Jutteau <j.jutteau@gmail.com>
188 Keilla Menezes <keilla@colivre.coop.br> 188 Keilla Menezes <keilla@colivre.coop.br>
189 Larissa Reis <larissa@colivre.coop.br> 189 Larissa Reis <larissa@colivre.coop.br>
190 Larissa Reis <reiss.larissa@gmail.com> 190 Larissa Reis <reiss.larissa@gmail.com>
191 Leandro Alves <leandrosustenido@gmail.com> 191 Leandro Alves <leandrosustenido@gmail.com>
192 -Leandro Nunes dos Santos <81665687568@serpro-1541727.Home>  
193 Leandro Nunes dos Santos <81665687568@serpro-1541727.(none)> 192 Leandro Nunes dos Santos <81665687568@serpro-1541727.(none)>
194 -Leandro Nunes dos Santos <leandronunes@gmail.com> 193 +Leandro Nunes dos Santos <81665687568@serpro-1541727.Home>
195 Leandro Nunes dos Santos <leandro.santos@serpro.gov.br> 194 Leandro Nunes dos Santos <leandro.santos@serpro.gov.br>
  195 +Leandro Nunes dos Santos <leandronunes@gmail.com>
196 LinguÁgil 2010 <linguagil.bahia@gmail.com> 196 LinguÁgil 2010 <linguagil.bahia@gmail.com>
197 Lucas Kanashiro <kanashiro.duarte@gmail.com> 197 Lucas Kanashiro <kanashiro.duarte@gmail.com>
198 Lucas Melo <lucas@colivre.coop.br> 198 Lucas Melo <lucas@colivre.coop.br>
199 Lucas Melo <lucaspradomelo@gmail.com> 199 Lucas Melo <lucaspradomelo@gmail.com>
200 Luciano <lucianopcbr@gmail.com> 200 Luciano <lucianopcbr@gmail.com>
  201 +Luciano Prestes Cavacanti <lucianopcbr@gmail.com>
201 Luciano Prestes Cavalcanti <lucianopcbr@gmail.com> 202 Luciano Prestes Cavalcanti <lucianopcbr@gmail.com>
202 Luis David Aguilar Carlos <ludwig9003@gmail.com> 203 Luis David Aguilar Carlos <ludwig9003@gmail.com>
203 Luiz Fernando de Freitas Matos <luiz@luizff.matos@gmail.com> 204 Luiz Fernando de Freitas Matos <luiz@luizff.matos@gmail.com>
  205 +M for Momo <mo@rtnp.org>
  206 +Marcelo Júnior <maljunior@gmail.com>
204 Marcos <marcos.rpj2@gmail.com> 207 Marcos <marcos.rpj2@gmail.com>
205 Marcos Ramos <ms.ramos@outlook.com> 208 Marcos Ramos <ms.ramos@outlook.com>
206 Martín Olivera <molivera@solar.org.ar> 209 Martín Olivera <molivera@solar.org.ar>
207 Maurilio Atila <cabelotaina@gmail.com> 210 Maurilio Atila <cabelotaina@gmail.com>
208 -M for Momo <mo@rtnp.org>  
209 Michal Čihař <michal@cihar.com> 211 Michal Čihař <michal@cihar.com>
  212 +Michel Felipe <mfelipeof@gmail.com>
210 Moises Machado <moises@colivre.coop.br> 213 Moises Machado <moises@colivre.coop.br>
211 -Naíla Alves <naila@colivre.coop.br>  
212 Nanda Lopes <nanda.listas+psl@gmail.com> 214 Nanda Lopes <nanda.listas+psl@gmail.com>
  215 +Naíla Alves <naila@colivre.coop.br>
213 Niemand Jedermann <predatorix@web.de> 216 Niemand Jedermann <predatorix@web.de>
214 Parley Martins <parleypachecomartins@gmail.com> 217 Parley Martins <parleypachecomartins@gmail.com>
215 Paulo Meirelles + Alessandro Palmeira + João M. M. da Silva <paulo@softwarelivre.org> 218 Paulo Meirelles + Alessandro Palmeira + João M. M. da Silva <paulo@softwarelivre.org>
@@ -217,8 +220,8 @@ Paulo Meirelles + Alessandro Palmeira &lt;paulo@softwarelivre.org&gt; @@ -217,8 +220,8 @@ Paulo Meirelles + Alessandro Palmeira &lt;paulo@softwarelivre.org&gt;
217 Paulo Meirelles + Carlos Morais <paulo@softwarelivre.org> 220 Paulo Meirelles + Carlos Morais <paulo@softwarelivre.org>
218 Paulo Meirelles + Diego Araújo <paulo@softwarelivre.org> 221 Paulo Meirelles + Diego Araújo <paulo@softwarelivre.org>
219 Paulo Meirelles + João M. M. da Silva <paulo@softwarelivre.org> 222 Paulo Meirelles + João M. M. da Silva <paulo@softwarelivre.org>
220 -Paulo Meirelles <paulo@softwarelivre.org>  
221 Paulo Meirelles + Rafael Manzo <paulo@softwarelivre.org> 223 Paulo Meirelles + Rafael Manzo <paulo@softwarelivre.org>
  224 +Paulo Meirelles <paulo@softwarelivre.org>
222 Rafael Gomes <rafaelgomes@techfree.com.br> 225 Rafael Gomes <rafaelgomes@techfree.com.br>
223 Rafael Manzo + Alessandro Palmeira <rr.manzo@gmail.com> 226 Rafael Manzo + Alessandro Palmeira <rr.manzo@gmail.com>
224 Rafael Manzo + Daniel Alves <danpaulalves@gmail.com> 227 Rafael Manzo + Daniel Alves <danpaulalves@gmail.com>
@@ -233,37 +236,46 @@ Rafael Reggiani Manzo + Diego Araújo &lt;rr.manzo@gmail.com&gt; @@ -233,37 +236,46 @@ Rafael Reggiani Manzo + Diego Araújo &lt;rr.manzo@gmail.com&gt;
233 Rafael Reggiani Manzo + João M. M. da Silva <rr.manzo@gmail.com> 236 Rafael Reggiani Manzo + João M. M. da Silva <rr.manzo@gmail.com>
234 Rafael Reggiani Manzo <rr.manzo@gmail.com> 237 Rafael Reggiani Manzo <rr.manzo@gmail.com>
235 Raphaël Rousseau <raph@r4f.org> 238 Raphaël Rousseau <raph@r4f.org>
236 -Raquel Lira <raquel.lira@gmail.com>  
237 Raquel <rcordioli@gmail.com> 239 Raquel <rcordioli@gmail.com>
  240 +Raquel Lira <raquel.lira@gmail.com>
238 Renan Teruo + Caio Salgado <renanteruoc@gmail.com> 241 Renan Teruo + Caio Salgado <renanteruoc@gmail.com>
239 -Renan Teruoc + Diego Araujo <renanteruoc@gmail.com>  
240 Renan Teruo + Diego Araujo <renanteruoc@gmail.com> 242 Renan Teruo + Diego Araujo <renanteruoc@gmail.com>
241 Renan Teruo + Diego Araújo <renanteruoc@gmail.com> 243 Renan Teruo + Diego Araújo <renanteruoc@gmail.com>
242 Renan Teruo + Paulo Meirelles <renanteruoc@gmail.com> 244 Renan Teruo + Paulo Meirelles <renanteruoc@gmail.com>
243 Renan Teruo + Rafael Manzo <renanteruoc@gmail.com> 245 Renan Teruo + Rafael Manzo <renanteruoc@gmail.com>
  246 +Renan Teruoc + Diego Araujo <renanteruoc@gmail.com>
244 Rodrigo Souto + Ana Losnak + Daniel Bucher + Caio Almeida + Leandro Nunes + Daniela Feitosa + Mariel Zasso <noosfero-br@listas.softwarelivre.org> 247 Rodrigo Souto + Ana Losnak + Daniel Bucher + Caio Almeida + Leandro Nunes + Daniela Feitosa + Mariel Zasso <noosfero-br@listas.softwarelivre.org>
245 Rodrigo Souto <rodrigo@colivre.coop.br> 248 Rodrigo Souto <rodrigo@colivre.coop.br>
246 Ronny Kursawe <kursawe.ronny@googlemail.com> 249 Ronny Kursawe <kursawe.ronny@googlemail.com>
247 -root <root@debian.sdr.serpro>  
248 Samuel R. C. Vale <srcvale@holoscopio.com> 250 Samuel R. C. Vale <srcvale@holoscopio.com>
  251 +TWS <tablettws@gmail.com>
249 Tallys Martins <tallysmartins@gmail.com> 252 Tallys Martins <tallysmartins@gmail.com>
250 Tallys Martins <tallysmartins@yahoo.com.br> 253 Tallys Martins <tallysmartins@yahoo.com.br>
251 -tallys <tallys@tallys>  
252 -tallys <tallys@tallys.(none)>  
253 Thiago Casotti <thiago.casotti@uol.com.br> 254 Thiago Casotti <thiago.casotti@uol.com.br>
  255 +Thiago Ribeiro <thiagitosouza@hotmail.com>
254 Thiago Zoroastro <thiago.zoroastro@bol.com.br> 256 Thiago Zoroastro <thiago.zoroastro@bol.com.br>
255 Tuux <tuxa@galaxie.eu.org> 257 Tuux <tuxa@galaxie.eu.org>
256 -TWS <tablettws@gmail.com>  
257 Valessio Brito <contato@valessiobrito.com.br> 258 Valessio Brito <contato@valessiobrito.com.br>
258 Valessio Brito <contato@valessiobrito.info> 259 Valessio Brito <contato@valessiobrito.info>
259 Valessio Brito <valessio@gmail.com> 260 Valessio Brito <valessio@gmail.com>
260 -vfcosta <vfcosta@gmail.com>  
261 Victor Carvalho <victorhugodf.ac@gmail.com> 261 Victor Carvalho <victorhugodf.ac@gmail.com>
262 Victor Costa <vfcosta@gmail.com> 262 Victor Costa <vfcosta@gmail.com>
263 Victor Hugo Alves de Carvalho <victorhugodf.ac@gmail.com> 263 Victor Hugo Alves de Carvalho <victorhugodf.ac@gmail.com>
264 Vinicius Cubas Brand <viniciuscb@gmail.com> 264 Vinicius Cubas Brand <viniciuscb@gmail.com>
265 Visita <visita@debian.(none)> 265 Visita <visita@debian.(none)>
266 Yann Lugrin <yann.lugrin@liquid-concept.ch> 266 Yann Lugrin <yann.lugrin@liquid-concept.ch>
  267 +alcampelo <alcampelo@alcampelo.(none)>
  268 +analosnak <analosnak@gmail.com>
  269 +daniel <dtygel@eita.org.br>
  270 +diegoamc <diegoamc90@gmail.com>
  271 +dtygel <dtygel@gmail.com>
  272 +juniorsilva <juniorsilva@QonoS.localhost.localdomain>
  273 +root <root@17edebf1ae91>
  274 +root <root@debian.sdr.serpro>
  275 +tallys <tallys@tallys.(none)>
  276 +tallys <tallys@tallys>
  277 +vfcosta <vfcosta@gmail.com>
  278 +Ábner Silva de Oliveira <abner.oliveira@serpro.gov.br>
267 279
268 Ideas, specifications and incentive 280 Ideas, specifications and incentive
269 =================================== 281 ===================================
1 source "https://rubygems.org" 1 source "https://rubygems.org"
2 -gem 'rails', '~> 3.2.21' 2 +gem 'rails', '~> 3.2.22'
3 gem 'minitest', '~> 3.2.0' 3 gem 'minitest', '~> 3.2.0'
4 gem 'fast_gettext', '~> 0.6.8' 4 gem 'fast_gettext', '~> 0.6.8'
5 gem 'acts-as-taggable-on', '~> 3.4.2' 5 gem 'acts-as-taggable-on', '~> 3.4.2'
@@ -18,7 +18,7 @@ gem &#39;exception_notification&#39;, &#39;~&gt; 4.0.1&#39; @@ -18,7 +18,7 @@ gem &#39;exception_notification&#39;, &#39;~&gt; 4.0.1&#39;
18 gem 'gettext', '~> 2.2.1', :require => false 18 gem 'gettext', '~> 2.2.1', :require => false
19 gem 'locale', '~> 2.0.5' 19 gem 'locale', '~> 2.0.5'
20 gem 'whenever', :require => false 20 gem 'whenever', :require => false
21 -gem 'eita-jrails', '>= 0.9.5', :require => 'jrails' 21 +gem 'eita-jrails', '= 0.9.5', :require => 'jrails'
22 gem 'grape', '~> 0.11.0' 22 gem 'grape', '~> 0.11.0'
23 gem 'grape-entity' 23 gem 'grape-entity'
24 gem 'grape-swagger' 24 gem 'grape-swagger'
@@ -26,6 +26,10 @@ gem &#39;grape_logging&#39; @@ -26,6 +26,10 @@ gem &#39;grape_logging&#39;
26 gem 'api-pagination', '~> 4.1.1' 26 gem 'api-pagination', '~> 4.1.1'
27 gem 'rack-cors' 27 gem 'rack-cors'
28 gem 'rack-contrib' 28 gem 'rack-contrib'
  29 +#gem 'grape-swagger-rails'
  30 +
  31 +# FIXME list here all actual dependencies (i.e. the ones in debian/control),
  32 +# with their GEM names (not the Debian package names)
29 33
30 # asset pipeline 34 # asset pipeline
31 gem 'uglifier', '>= 1.0.3' 35 gem 'uglifier', '>= 1.0.3'
Gemfile.lock 0 → 100644
@@ -0,0 +1,277 @@ @@ -0,0 +1,277 @@
  1 +GEM
  2 + remote: https://rubygems.org/
  3 + specs:
  4 + RedCloth (4.2.9)
  5 + actionmailer (3.2.22)
  6 + actionpack (= 3.2.22)
  7 + mail (~> 2.5.4)
  8 + actionpack (3.2.22)
  9 + activemodel (= 3.2.22)
  10 + activesupport (= 3.2.22)
  11 + builder (~> 3.0.0)
  12 + erubis (~> 2.7.0)
  13 + journey (~> 1.0.4)
  14 + rack (~> 1.4.5)
  15 + rack-cache (~> 1.2)
  16 + rack-test (~> 0.6.1)
  17 + sprockets (~> 2.2.1)
  18 + activemodel (3.2.22)
  19 + activesupport (= 3.2.22)
  20 + builder (~> 3.0.0)
  21 + activerecord (3.2.22)
  22 + activemodel (= 3.2.22)
  23 + activesupport (= 3.2.22)
  24 + arel (~> 3.0.2)
  25 + tzinfo (~> 0.3.29)
  26 + activeresource (3.2.22)
  27 + activemodel (= 3.2.22)
  28 + activesupport (= 3.2.22)
  29 + activesupport (3.2.22)
  30 + i18n (~> 0.6, >= 0.6.4)
  31 + multi_json (~> 1.0)
  32 + acts-as-taggable-on (3.4.4)
  33 + activerecord (>= 3.2, < 5)
  34 + api-pagination (4.1.1)
  35 + arel (3.0.3)
  36 + axiom-types (0.1.1)
  37 + descendants_tracker (~> 0.0.4)
  38 + ice_nine (~> 0.11.0)
  39 + thread_safe (~> 0.3, >= 0.3.1)
  40 + builder (3.0.4)
  41 + capybara (2.1.0)
  42 + mime-types (>= 1.16)
  43 + nokogiri (>= 1.3.3)
  44 + rack (>= 1.0.0)
  45 + rack-test (>= 0.5.4)
  46 + xpath (~> 2.0)
  47 + childprocess (0.5.6)
  48 + ffi (~> 1.0, >= 1.0.11)
  49 + chronic (0.10.2)
  50 + coercible (1.0.0)
  51 + descendants_tracker (~> 0.0.1)
  52 + columnize (0.9.0)
  53 + cucumber (1.0.6)
  54 + builder (>= 2.1.2)
  55 + diff-lcs (>= 1.1.2)
  56 + gherkin (~> 2.4.18)
  57 + json (>= 1.4.6)
  58 + term-ansicolor (>= 1.0.6)
  59 + cucumber-rails (1.0.6)
  60 + capybara (>= 1.1.1)
  61 + cucumber (>= 1.0.6)
  62 + nokogiri (>= 1.5.0)
  63 + daemons (1.1.9)
  64 + dalli (2.7.4)
  65 + database_cleaner (1.2.0)
  66 + debugger (1.6.8)
  67 + columnize (>= 0.3.1)
  68 + debugger-linecache (~> 1.2.0)
  69 + debugger-ruby_core_source (~> 1.3.5)
  70 + debugger-linecache (1.2.0)
  71 + debugger-ruby_core_source (1.3.8)
  72 + descendants_tracker (0.0.4)
  73 + thread_safe (~> 0.3, >= 0.3.1)
  74 + diff-lcs (1.2.5)
  75 + eita-jrails (0.9.5)
  76 + actionpack (~> 3.2, >= 3.1.0)
  77 + activesupport (~> 3.2, >= 3.0.0)
  78 + equalizer (0.0.11)
  79 + erubis (2.7.0)
  80 + eventmachine (1.0.7)
  81 + exception_notification (4.0.1)
  82 + actionmailer (>= 3.0.4)
  83 + activesupport (>= 3.0.4)
  84 + execjs (2.5.2)
  85 + fast_gettext (0.6.12)
  86 + ffi (1.9.10)
  87 + gettext (2.2.1)
  88 + locale
  89 + gherkin (2.4.21)
  90 + json (>= 1.4.6)
  91 + git-version-bump (0.15.1)
  92 + grape (0.11.0)
  93 + activesupport
  94 + builder
  95 + hashie (>= 2.1.0)
  96 + multi_json (>= 1.3.2)
  97 + multi_xml (>= 0.5.2)
  98 + rack (>= 1.3.0)
  99 + rack-accept
  100 + rack-mount
  101 + virtus (>= 1.0.0)
  102 + grape-entity (0.4.5)
  103 + activesupport
  104 + multi_json (>= 1.3.2)
  105 + grape-swagger (0.10.1)
  106 + grape (>= 0.8.0)
  107 + grape-entity
  108 + grape_logging (1.1.2)
  109 + grape
  110 + hashie (3.4.2)
  111 + hike (1.2.3)
  112 + i18n (0.7.0)
  113 + ice_nine (0.11.1)
  114 + journey (1.0.4)
  115 + json (1.8.3)
  116 + locale (2.0.9)
  117 + magic (0.2.9)
  118 + ffi (>= 0.6.3)
  119 + mail (2.5.4)
  120 + mime-types (~> 1.16)
  121 + treetop (~> 1.4.8)
  122 + metaclass (0.0.4)
  123 + mime-types (1.25.1)
  124 + mini_portile (0.6.2)
  125 + minitest (3.2.0)
  126 + mocha (1.1.0)
  127 + metaclass (~> 0.0.1)
  128 + multi_json (1.11.2)
  129 + multi_xml (0.5.5)
  130 + nokogiri (1.6.6.2)
  131 + mini_portile (~> 0.6.0)
  132 + pg (0.13.2)
  133 + polyglot (0.3.5)
  134 + rack (1.4.7)
  135 + rack-accept (0.4.5)
  136 + rack (>= 0.4)
  137 + rack-cache (1.2)
  138 + rack (>= 0.4)
  139 + rack-contrib (1.3.0)
  140 + git-version-bump (~> 0.15)
  141 + rack (~> 1.4)
  142 + rack-cors (0.4.0)
  143 + rack-mount (0.8.3)
  144 + rack (>= 1.0.0)
  145 + rack-ssl (1.3.4)
  146 + rack
  147 + rack-test (0.6.3)
  148 + rack (>= 1.0)
  149 + rails (3.2.22)
  150 + actionmailer (= 3.2.22)
  151 + actionpack (= 3.2.22)
  152 + activerecord (= 3.2.22)
  153 + activeresource (= 3.2.22)
  154 + activesupport (= 3.2.22)
  155 + bundler (~> 1.0)
  156 + railties (= 3.2.22)
  157 + rails_autolink (1.1.6)
  158 + rails (> 3.1)
  159 + railties (3.2.22)
  160 + actionpack (= 3.2.22)
  161 + activesupport (= 3.2.22)
  162 + rack-ssl (~> 1.3.2)
  163 + rake (>= 0.8.7)
  164 + rdoc (~> 3.4)
  165 + thor (>= 0.14.6, < 2.0)
  166 + rake (10.4.2)
  167 + rdoc (3.12.2)
  168 + json (~> 1.4)
  169 + rest-client (1.6.9)
  170 + mime-types (~> 1.16)
  171 + rmagick (2.13.4)
  172 + rspec (2.14.1)
  173 + rspec-core (~> 2.14.0)
  174 + rspec-expectations (~> 2.14.0)
  175 + rspec-mocks (~> 2.14.0)
  176 + rspec-core (2.14.8)
  177 + rspec-expectations (2.14.5)
  178 + diff-lcs (>= 1.1.3, < 2.0)
  179 + rspec-mocks (2.14.6)
  180 + rspec-rails (2.14.2)
  181 + actionpack (>= 3.0)
  182 + activemodel (>= 3.0)
  183 + activesupport (>= 3.0)
  184 + railties (>= 3.0)
  185 + rspec-core (~> 2.14.0)
  186 + rspec-expectations (~> 2.14.0)
  187 + rspec-mocks (~> 2.14.0)
  188 + ruby-feedparser (0.9.3)
  189 + magic
  190 + rubyzip (1.1.7)
  191 + sass (3.4.15)
  192 + sass-rails (3.2.6)
  193 + railties (~> 3.2.0)
  194 + sass (>= 3.1.10)
  195 + tilt (~> 1.3)
  196 + selenium-webdriver (2.39.0)
  197 + childprocess (>= 0.2.5)
  198 + multi_json (~> 1.0)
  199 + rubyzip (~> 1.0)
  200 + websocket (~> 1.0.4)
  201 + sprockets (2.2.3)
  202 + hike (~> 1.2)
  203 + multi_json (~> 1.0)
  204 + rack (~> 1.0)
  205 + tilt (~> 1.1, != 1.3.0)
  206 + term-ansicolor (1.3.2)
  207 + tins (~> 1.0)
  208 + thin (1.3.1)
  209 + daemons (>= 1.0.9)
  210 + eventmachine (>= 0.12.6)
  211 + rack (>= 1.0.0)
  212 + thor (0.19.1)
  213 + thread_safe (0.3.5)
  214 + tilt (1.4.1)
  215 + tins (1.5.4)
  216 + treetop (1.4.15)
  217 + polyglot
  218 + polyglot (>= 0.3.1)
  219 + tzinfo (0.3.44)
  220 + uglifier (2.7.1)
  221 + execjs (>= 0.3.0)
  222 + json (>= 1.8.0)
  223 + virtus (1.0.5)
  224 + axiom-types (~> 0.1)
  225 + coercible (~> 1.0)
  226 + descendants_tracker (~> 0.0, >= 0.0.3)
  227 + equalizer (~> 0.0, >= 0.0.9)
  228 + websocket (1.0.7)
  229 + whenever (0.9.4)
  230 + chronic (>= 0.6.3)
  231 + will_paginate (3.0.7)
  232 + xpath (2.0.0)
  233 + nokogiri (~> 1.3)
  234 +
  235 +PLATFORMS
  236 + ruby
  237 +
  238 +DEPENDENCIES
  239 + RedCloth (~> 4.2.9)
  240 + acts-as-taggable-on (~> 3.4.2)
  241 + api-pagination (~> 4.1.1)
  242 + capybara (~> 2.1.0)
  243 + cucumber (~> 1.0.6)
  244 + cucumber-rails (~> 1.0.6)
  245 + daemons (~> 1.1.5)
  246 + dalli (~> 2.7.0)
  247 + database_cleaner (~> 1.2.0)
  248 + debugger
  249 + eita-jrails (= 0.9.5)
  250 + exception_notification (~> 4.0.1)
  251 + fast_gettext (~> 0.6.8)
  252 + gettext (~> 2.2.1)
  253 + grape (~> 0.11.0)
  254 + grape-entity
  255 + grape-swagger
  256 + grape_logging
  257 + locale (~> 2.0.5)
  258 + minitest (~> 3.2.0)
  259 + mocha (~> 1.1.0)
  260 + nokogiri (~> 1.6.0)
  261 + pg (~> 0.13.2)
  262 + rack-contrib
  263 + rack-cors
  264 + rails (~> 3.2.22)
  265 + rails_autolink (~> 1.1.5)
  266 + rake
  267 + rest-client (~> 1.6.7)
  268 + rmagick (~> 2.13.1)
  269 + rspec (~> 2.14.0)
  270 + rspec-rails (~> 2.14.1)
  271 + ruby-feedparser (~> 0.7)
  272 + sass-rails
  273 + selenium-webdriver (~> 2.39.0)
  274 + thin (~> 1.3.1)
  275 + uglifier (>= 1.0.3)
  276 + whenever
  277 + will_paginate (~> 3.0.3)
app/controllers/my_profile/cms_controller.rb
@@ -94,6 +94,11 @@ class CmsController &lt; MyProfileController @@ -94,6 +94,11 @@ class CmsController &lt; MyProfileController
94 record_coming 94 record_coming
95 if request.post? 95 if request.post?
96 @article.image = nil if params[:remove_image] == 'true' 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
97 @article.last_changed_by = user 102 @article.last_changed_by = user
98 if @article.update_attributes(params[:article]) 103 if @article.update_attributes(params[:article])
99 if !continue 104 if !continue
@@ -105,6 +110,11 @@ class CmsController &lt; MyProfileController @@ -105,6 +110,11 @@ class CmsController &lt; MyProfileController
105 end 110 end
106 end 111 end
107 end 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
108 end 118 end
109 119
110 def new 120 def new
app/controllers/my_profile/manage_products_controller.rb
@@ -35,7 +35,7 @@ class ManageProductsController &lt; ApplicationController @@ -35,7 +35,7 @@ class ManageProductsController &lt; ApplicationController
35 end 35 end
36 36
37 def categories_for_selection 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 @object_name = params[:object_name] 39 @object_name = params[:object_name]
40 if @category 40 if @category
41 @categories = @category.children 41 @categories = @category.children
@@ -95,6 +95,20 @@ class ManageProductsController &lt; ApplicationController @@ -95,6 +95,20 @@ class ManageProductsController &lt; ApplicationController
95 end 95 end
96 end 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 def add_input 112 def add_input
99 @product = @profile.products.find(params[:id]) 113 @product = @profile.products.find(params[:id])
100 @input = @product.inputs.build 114 @input = @product.inputs.build
app/controllers/my_profile/maps_controller.rb
@@ -16,6 +16,7 @@ class MapsController &lt; MyProfileController @@ -16,6 +16,7 @@ class MapsController &lt; MyProfileController
16 16
17 Profile.transaction do 17 Profile.transaction do
18 if profile.update_attributes!(params[:profile_data]) 18 if profile.update_attributes!(params[:profile_data])
  19 + BlockSweeper.expire_blocks profile.blocks.select{ |b| b.class == LocationBlock }
19 session[:notice] = _('Address was updated successfully!') 20 session[:notice] = _('Address was updated successfully!')
20 redirect_to :action => 'edit_location' 21 redirect_to :action => 'edit_location'
21 end 22 end
app/controllers/public/account_controller.rb
@@ -98,11 +98,8 @@ class AccountController &lt; ApplicationController @@ -98,11 +98,8 @@ class AccountController &lt; ApplicationController
98 @block_bot = !!session[:may_be_a_bot] 98 @block_bot = !!session[:may_be_a_bot]
99 @invitation_code = params[:invitation_code] 99 @invitation_code = params[:invitation_code]
100 begin 100 begin
101 - @user = User.new(params[:user])  
102 - @user.terms_of_use = environment.terms_of_use  
103 - @user.environment = environment 101 + @user = User.build(params[:user], params[:profile_data], environment)
104 @terms_of_use = environment.terms_of_use 102 @terms_of_use = environment.terms_of_use
105 - @user.person_data = params[:profile_data]  
106 @user.return_to = session[:return_to] 103 @user.return_to = session[:return_to]
107 @person = Person.new(params[:profile_data]) 104 @person = Person.new(params[:profile_data])
108 @person.environment = @user.environment 105 @person.environment = @user.environment
app/controllers/public/api_controller.rb 0 → 100644
@@ -0,0 +1,19 @@ @@ -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/content_viewer_controller.rb
@@ -15,6 +15,7 @@ class ContentViewerController &lt; ApplicationController @@ -15,6 +15,7 @@ class ContentViewerController &lt; ApplicationController
15 path = get_path(params[:page], params[:format]) 15 path = get_path(params[:page], params[:format])
16 16
17 @version = params[:version].to_i 17 @version = params[:version].to_i
  18 + @npage = params[:npage] || '1'
18 19
19 if path.blank? 20 if path.blank?
20 @page = profile.home_page 21 @page = profile.home_page
@@ -131,7 +132,7 @@ class ContentViewerController &lt; ApplicationController @@ -131,7 +132,7 @@ class ContentViewerController &lt; ApplicationController
131 end 132 end
132 133
133 unless @page.display_to?(user) 134 unless @page.display_to?(user)
134 - if !profile.visible? || profile.secret? || (user && user.follows?(profile)) 135 + if !profile.visible? || profile.secret? || (user && user.follows?(profile)) || user.blank?
135 render_access_denied 136 render_access_denied
136 else #!profile.public? 137 else #!profile.public?
137 private_profile_partial_parameters 138 private_profile_partial_parameters
app/helpers/application_helper.rb
@@ -1195,7 +1195,7 @@ module ApplicationHelper @@ -1195,7 +1195,7 @@ module ApplicationHelper
1195 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")) 1195 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"))
1196 end 1196 end
1197 1197
1198 - (_("<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'))) + 1198 + (_("<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'))) +
1199 render_environment_features(:usermenu) + 1199 render_environment_features(:usermenu) +
1200 admin_link + 1200 admin_link +
1201 manage_enterprises + 1201 manage_enterprises +
@@ -1226,35 +1226,6 @@ module ApplicationHelper @@ -1226,35 +1226,6 @@ module ApplicationHelper
1226 list.sort.inject(Hash.new(0)){|h,i| h[i] += 1; h }.collect{ |x, n| [n, connector, x].join(" ") }.sort 1226 list.sort.inject(Hash.new(0)){|h,i| h[i] += 1; h }.collect{ |x, n| [n, connector, x].join(" ") }.sort
1227 end 1227 end
1228 1228
1229 - #FIXME Use time_ago_in_words instead of this method if you're using Rails 2.2+  
1230 - def time_ago_as_sentence(from_time, include_seconds = false)  
1231 - to_time = Time.now  
1232 - from_time = Time.parse(from_time.to_s)  
1233 - from_time = from_time.to_time if from_time.respond_to?(:to_time)  
1234 - to_time = to_time.to_time if to_time.respond_to?(:to_time)  
1235 - distance_in_minutes = (((to_time - from_time).abs)/60).round  
1236 - distance_in_seconds = ((to_time - from_time).abs).round  
1237 - case distance_in_minutes  
1238 - when 0..1  
1239 - return (distance_in_minutes == 0) ? _('less than a minute') : _('1 minute') unless include_seconds  
1240 - case distance_in_seconds  
1241 - when 0..4 then _('less than 5 seconds')  
1242 - when 5..9 then _('less than 10 seconds')  
1243 - when 10..19 then _('less than 20 seconds')  
1244 - when 20..39 then _('half a minute')  
1245 - when 40..59 then _('less than a minute')  
1246 - else _('1 minute')  
1247 - end  
1248 -  
1249 - when 2..44 then _('%{distance} minutes ago') % { :distance => distance_in_minutes }  
1250 - when 45..89 then _('about 1 hour ago')  
1251 - when 90..1439 then _('about %{distance} hours ago') % { :distance => (distance_in_minutes.to_f / 60.0).round }  
1252 - when 1440..2879 then _('1 day ago')  
1253 - when 2880..10079 then _('%{distance} days ago') % { :distance => (distance_in_minutes / 1440).round }  
1254 - else show_time(from_time)  
1255 - end  
1256 - end  
1257 -  
1258 def comment_balloon(options = {}, &block) 1229 def comment_balloon(options = {}, &block)
1259 wrapper = content_tag(:div, capture(&block), :class => 'comment-balloon-content') 1230 wrapper = content_tag(:div, capture(&block), :class => 'comment-balloon-content')
1260 (1..8).to_a.reverse.each { |i| wrapper = content_tag(:div, wrapper, :class => "comment-wrapper-#{i}") } 1231 (1..8).to_a.reverse.each { |i| wrapper = content_tag(:div, wrapper, :class => "comment-wrapper-#{i}") }
@@ -1273,7 +1244,7 @@ module ApplicationHelper @@ -1273,7 +1244,7 @@ module ApplicationHelper
1273 1244
1274 def task_information(task) 1245 def task_information(task)
1275 values = {} 1246 values = {}
1276 - values.merge!({:requestor => link_to(task.requestor.name, task.requestor.public_profile_url)}) if task.requestor 1247 + values.merge!({:requestor => link_to(task.requestor.name, task.requestor.url)}) if task.requestor
1277 values.merge!({:subject => content_tag('span', task.subject, :class=>'task_target')}) if task.subject 1248 values.merge!({:subject => content_tag('span', task.subject, :class=>'task_target')}) if task.subject
1278 values.merge!({:linked_subject => link_to(content_tag('span', task.linked_subject[:text], :class => 'task_target'), task.linked_subject[:url])}) if task.linked_subject 1249 values.merge!({:linked_subject => link_to(content_tag('span', task.linked_subject[:text], :class => 'task_target'), task.linked_subject[:url])}) if task.linked_subject
1279 values.merge!(task.information[:variables]) if task.information[:variables] 1250 values.merge!(task.information[:variables]) if task.information[:variables]
app/helpers/blog_helper.rb
@@ -22,7 +22,9 @@ module BlogHelper @@ -22,7 +22,9 @@ module BlogHelper
22 :param_name => 'npage', 22 :param_name => 'npage',
23 :previous_label => _('&laquo; Newer posts'), 23 :previous_label => _('&laquo; Newer posts'),
24 :next_label => _('Older posts &raquo;'), 24 :next_label => _('Older posts &raquo;'),
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 }) if articles.present? && conf[:paginate] 28 }) if articles.present? && conf[:paginate]
27 content = [] 29 content = []
28 artic_len = articles.length 30 artic_len = articles.length
@@ -44,7 +46,7 @@ module BlogHelper @@ -44,7 +46,7 @@ module BlogHelper
44 end 46 end
45 47
46 def display_post(article, format = 'full') 48 def display_post(article, format = 'full')
47 - no_comments = (format == 'full') ? false : true 49 + no_comments = (format == 'full' || format == 'compact' ) ? false : true
48 title = article_title(article, :no_comments => no_comments) 50 title = article_title(article, :no_comments => no_comments)
49 method = "display_#{format.split('+')[0]}_format" 51 method = "display_#{format.split('+')[0]}_format"
50 html = send(method, FilePresenter.for(article)).html_safe 52 html = send(method, FilePresenter.for(article)).html_safe
@@ -55,8 +57,12 @@ module BlogHelper @@ -55,8 +57,12 @@ module BlogHelper
55 else 57 else
56 '<div class="post-pic" style="background-image:url('+img+')"></div>' 58 '<div class="post-pic" style="background-image:url('+img+')"></div>'
57 end 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 end 66 end
61 67
62 def display_full_format(article) 68 def display_full_format(article)
app/helpers/comment_helper.rb
1 module CommentHelper 1 module CommentHelper
  2 + include DatesHelper
2 3
3 def article_title(article, args = {}) 4 def article_title(article, args = {})
4 title = article.title 5 title = article.title
@@ -15,7 +16,7 @@ module CommentHelper @@ -15,7 +16,7 @@ module CommentHelper
15 content_tag('span', show_date(article.published_at), :class => 'date') + 16 content_tag('span', show_date(article.published_at), :class => 'date') +
16 content_tag('span', [_(", by %s") % link_to(article.author_name, article.author_url)], :class => 'author') + 17 content_tag('span', [_(", by %s") % link_to(article.author_name, article.author_url)], :class => 'author') +
17 content_tag('span', comments, :class => 'comments'), 18 content_tag('span', comments, :class => 'comments'),
18 - :class => 'created-at' 19 + :class => 'publishing-info'
19 ) 20 )
20 end 21 end
21 title 22 title
app/helpers/content_viewer_helper.rb
@@ -2,6 +2,7 @@ module ContentViewerHelper @@ -2,6 +2,7 @@ module ContentViewerHelper
2 2
3 include BlogHelper 3 include BlogHelper
4 include ForumHelper 4 include ForumHelper
  5 + include DatesHelper
5 6
6 def display_number_of_comments(n) 7 def display_number_of_comments(n)
7 base_str = "<span class='comment-count hide'>#{n}</span>" 8 base_str = "<span class='comment-count hide'>#{n}</span>"
@@ -24,16 +25,35 @@ module ContentViewerHelper @@ -24,16 +25,35 @@ module ContentViewerHelper
24 unless args[:no_comments] || !article.accept_comments 25 unless args[:no_comments] || !article.accept_comments
25 comments = (" - %s") % link_to_comments(article) 26 comments = (" - %s") % link_to_comments(article)
26 end 27 end
  28 + date_format = show_with_right_format_date article
27 title << content_tag('span', 29 title << content_tag('span',
28 - content_tag('span', show_date(article.published_at), :class => 'date') + 30 + date_format +
29 content_tag('span', _(", by %s") % (article.author ? link_to(article.author_name, article.author_url) : article.author_name), :class => 'author') + 31 content_tag('span', _(", by %s") % (article.author ? link_to(article.author_name, article.author_url) : article.author_name), :class => 'author') +
30 content_tag('span', comments, :class => 'comments'), 32 content_tag('span', comments, :class => 'comments'),
31 - :class => 'created-at' 33 + :class => 'publishing-info'
32 ) 34 )
33 end 35 end
34 title 36 title
35 end 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_date(article.published_at, use_numbers , year, left_time), :class => 'date')
  55 + end
  56 +
37 def link_to_comments(article, args = {}) 57 def link_to_comments(article, args = {})
38 return '' unless article.accept_comments? 58 return '' unless article.accept_comments?
39 reference_to_article number_of_comments(article), article, 'comments_list' 59 reference_to_article number_of_comments(article), article, 'comments_list'
app/helpers/dates_helper.rb
@@ -2,6 +2,7 @@ require &#39;noosfero/i18n&#39; @@ -2,6 +2,7 @@ require &#39;noosfero/i18n&#39;
2 2
3 module DatesHelper 3 module DatesHelper
4 4
  5 + include ActionView::Helpers::DateHelper
5 def months 6 def months
6 I18n.t('date.month_names') 7 I18n.t('date.month_names')
7 end 8 end
@@ -15,10 +16,12 @@ module DatesHelper @@ -15,10 +16,12 @@ module DatesHelper
15 end 16 end
16 17
17 # formats a date for displaying. 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 if date && use_numbers 20 if date && use_numbers
20 date_format = year ? _('%{month}/%{day}/%{year}') : _('%{month}/%{day}') 21 date_format = year ? _('%{month}/%{day}/%{year}') : _('%{month}/%{day}')
21 date_format % { :day => date.day, :month => date.month, :year => date.year } 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 elsif date 25 elsif date
23 date_format = year ? _('%{month_name} %{day}, %{year}') : _('%{month_name} %{day}') 26 date_format = year ? _('%{month_name} %{day}, %{year}') : _('%{month_name} %{day}')
24 date_format % { :day => date.day, :month_name => month_name(date.month), :year => date.year } 27 date_format % { :day => date.day, :month_name => month_name(date.month), :year => date.year }
app/helpers/events_helper.rb
1 module EventsHelper 1 module EventsHelper
2 2
  3 + include DatesHelper
3 def list_events(date, events) 4 def list_events(date, events)
4 title = _('Events for %s') % show_date_month(date) 5 title = _('Events for %s') % show_date_month(date)
5 content_tag('h2', title) + 6 content_tag('h2', title) +
app/helpers/folder_helper.rb
1 -require 'short_filename'  
2 -  
3 module FolderHelper 1 module FolderHelper
4 2
5 - include ShortFilename  
6 include ArticleHelper 3 include ArticleHelper
7 4
8 def list_contents(configure={}) 5 def list_contents(configure={})
@@ -10,8 +7,8 @@ module FolderHelper @@ -10,8 +7,8 @@ module FolderHelper
10 configure[:list_type] ||= :folder 7 configure[:list_type] ||= :folder
11 if !configure[:contents].blank? 8 if !configure[:contents].blank?
12 configure[:contents] = configure[:contents].paginate( 9 configure[:contents] = configure[:contents].paginate(
13 - :order => "updated_at DESC",  
14 - :per_page => 10, 10 + :order => "name ASC",
  11 + :per_page => 30,
15 :page => params[:npage] 12 :page => params[:npage]
16 ) 13 )
17 14
@@ -25,49 +22,32 @@ module FolderHelper @@ -25,49 +22,32 @@ module FolderHelper
25 articles.select {|article| article.display_to?(user)} 22 articles.select {|article| article.display_to?(user)}
26 end 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 content_link = if content.image? 27 content_link = if content.image?
34 - link_to('&nbsp;' * (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 content.url.merge(:view => true) 30 content.url.merge(:view => true)
37 ) 31 )
38 else 32 else
39 - link_to('&nbsp;' * (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 end 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 end 38 end
59 39
60 - def icon_for_article(article) 40 + def icon_for_article(article, size = 'icon')
61 article = FilePresenter.for article 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 else 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 if article.kind_of?(UploadedFile) || article.kind_of?(FilePresenter) 49 if article.kind_of?(UploadedFile) || article.kind_of?(FilePresenter)
70 - klasses += ' icon-upload-file' 50 + klasses += " #{size}-upload-file"
71 end 51 end
72 klasses 52 klasses
73 end 53 end
app/helpers/forum_helper.rb
1 module ForumHelper 1 module ForumHelper
  2 + include ActionView::Helpers::DateHelper
2 3
3 def cms_label_for_new_children 4 def cms_label_for_new_children
4 _('New discussion topic') 5 _('New discussion topic')
@@ -42,9 +43,9 @@ module ForumHelper @@ -42,9 +43,9 @@ module ForumHelper
42 def last_topic_update(article) 43 def last_topic_update(article)
43 info = article.info_from_last_update 44 info = article.info_from_last_update
44 if info[:author_url] 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 else 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 end 49 end
49 end 50 end
50 51
app/helpers/manage_products_helper.rb
@@ -75,9 +75,12 @@ module ManageProductsHelper @@ -75,9 +75,12 @@ module ManageProductsHelper
75 end 75 end
76 76
77 def categories_container(categories_selection_html, hierarchy_html = '') 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 end 84 end
82 85
83 def select_for_categories(categories, level = 0) 86 def select_for_categories(categories, level = 0)
app/models/article.rb
@@ -28,7 +28,7 @@ class Article &lt; ActiveRecord::Base @@ -28,7 +28,7 @@ class Article &lt; ActiveRecord::Base
28 def initialize(*params) 28 def initialize(*params)
29 super 29 super
30 30
31 - if !params.blank? && params.first.has_key?(:profile) 31 + if !params.blank? && params.first.has_key?(:profile) && !params.first[:profile].blank?
32 profile = params.first[:profile] 32 profile = params.first[:profile]
33 self.published = false unless profile.public? 33 self.published = false unless profile.public?
34 end 34 end
@@ -133,15 +133,7 @@ class Article &lt; ActiveRecord::Base @@ -133,15 +133,7 @@ class Article &lt; ActiveRecord::Base
133 {:include => 'categories_including_virtual', :conditions => { 'categories.id' => category.id }} 133 {:include => 'categories_including_virtual', :conditions => { 'categories.id' => category.id }}
134 } 134 }
135 135
136 - #FIXME make this test  
137 - scope :newer_than, lambda { |reference_id|  
138 - {:conditions => ["articles.id > #{reference_id}"]}  
139 - }  
140 -  
141 - #FIXME make this test  
142 - scope :older_than, lambda { |reference_id|  
143 - {:conditions => ["articles.id < #{reference_id}"]}  
144 - } 136 + include TimeScopes
145 137
146 scope :by_range, lambda { |range| { 138 scope :by_range, lambda { |range| {
147 :conditions => [ 139 :conditions => [
@@ -748,8 +740,9 @@ class Article &lt; ActiveRecord::Base @@ -748,8 +740,9 @@ class Article &lt; ActiveRecord::Base
748 paragraphs.empty? ? '' : paragraphs.first.to_html 740 paragraphs.empty? ? '' : paragraphs.first.to_html
749 end 741 end
750 742
751 - def lead  
752 - abstract.blank? ? first_paragraph.html_safe : abstract.html_safe 743 + def lead(length = nil)
  744 + content = abstract.blank? ? first_paragraph.html_safe : abstract.html_safe
  745 + length.present? ? content.truncate(length) : content
753 end 746 end
754 747
755 def short_lead 748 def short_lead
app/models/blog.rb
@@ -76,9 +76,12 @@ class Blog &lt; Folder @@ -76,9 +76,12 @@ class Blog &lt; Folder
76 end 76 end
77 77
78 settings_items :visualization_format, :type => :string, :default => 'full' 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 alias :display_posts_in_current_language? :display_posts_in_current_language 86 alias :display_posts_in_current_language? :display_posts_in_current_language
84 87
app/models/comment.rb
@@ -20,16 +20,7 @@ class Comment &lt; ActiveRecord::Base @@ -20,16 +20,7 @@ class Comment &lt; ActiveRecord::Base
20 20
21 scope :without_reply, :conditions => ['reply_of_id IS NULL'] 21 scope :without_reply, :conditions => ['reply_of_id IS NULL']
22 22
23 - #FIXME make this test  
24 - scope :newer_than, lambda { |reference_id|  
25 - {:conditions => ["comments.id > #{reference_id}"]}  
26 - }  
27 -  
28 - #FIXME make this test  
29 - scope :older_than, lambda { |reference_id|  
30 - {:conditions => ["comments.id < #{reference_id}"]}  
31 - }  
32 - 23 + include TimeScopes
33 24
34 # unauthenticated authors: 25 # unauthenticated authors:
35 validates_presence_of :name, :if => (lambda { |record| !record.email.blank? }) 26 validates_presence_of :name, :if => (lambda { |record| !record.email.blank? })
app/models/environment.rb
@@ -3,7 +3,17 @@ @@ -3,7 +3,17 @@
3 # domains. 3 # domains.
4 class Environment < ActiveRecord::Base 4 class Environment < ActiveRecord::Base
5 5
6 - attr_accessible :name, :is_default, :signup_welcome_text_subject, :signup_welcome_text_body, :terms_of_use, :message_for_disabled_enterprise, :news_amount_by_folder, :default_language, :languages, :description, :organization_approval_method, :enabled_plugins, :enabled_features, :redirection_after_login, :redirection_after_signup, :contact_email, :theme, :reports_lower_bound, :noreply_email, :signup_welcome_screen_body, :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 has_many :users 18 has_many :users
9 19
@@ -14,6 +24,12 @@ class Environment &lt; ActiveRecord::Base @@ -14,6 +24,12 @@ class Environment &lt; ActiveRecord::Base
14 24
15 IDENTIFY_SCRIPTS = /(php[0-9s]?|[sp]htm[l]?|pl|py|cgi|rb)/ 25 IDENTIFY_SCRIPTS = /(php[0-9s]?|[sp]htm[l]?|pl|py|cgi|rb)/
16 26
  27 + validates_inclusion_of :date_format,
  28 + :in => [ 'numbers_with_year', 'numbers',
  29 + 'month_name_with_year', 'month_name',
  30 + 'past_time'],
  31 + :if => :date_format
  32 +
17 def self.verify_filename(filename) 33 def self.verify_filename(filename)
18 filename += '.txt' if File.extname(filename) =~ IDENTIFY_SCRIPTS 34 filename += '.txt' if File.extname(filename) =~ IDENTIFY_SCRIPTS
19 filename 35 filename
app/models/event.rb
@@ -98,47 +98,19 @@ class Event &lt; Article @@ -98,47 +98,19 @@ class Event &lt; Article
98 start_date..(end_date||start_date) 98 start_date..(end_date||start_date)
99 end 99 end
100 100
101 - # FIXME this shouldn't be needed  
102 - include ActionView::Helpers::TagHelper  
103 - include ActionView::Helpers::UrlHelper  
104 - include DatesHelper 101 + def first_paragraph
  102 + paragraphs = Nokogiri::HTML.fragment(self.body).css('p')
  103 + paragraphs.empty? ? '' : paragraphs.first.to_html
  104 + end
105 105
106 def to_html(options = {}) 106 def to_html(options = {})
  107 + event = self
  108 + format = options[:format]
107 109
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 110 + proc do
  111 + render :file => 'content_viewer/event_page', :locals => { :event => event,
  112 + :format => format }
139 end 113 end
140 -  
141 - result  
142 end 114 end
143 115
144 def duration 116 def duration
app/models/image.rb
@@ -23,7 +23,7 @@ class Image &lt; ActiveRecord::Base @@ -23,7 +23,7 @@ class Image &lt; ActiveRecord::Base
23 23
24 postgresql_attachment_fu 24 postgresql_attachment_fu
25 25
26 - attr_accessible :uploaded_data 26 + attr_accessible :uploaded_data, :label
27 27
28 def current_data 28 def current_data
29 File.file?(full_filename) ? File.read(full_filename) : nil 29 File.file?(full_filename) ? File.read(full_filename) : nil
app/models/organization.rb
@@ -8,13 +8,30 @@ class Organization &lt; Profile @@ -8,13 +8,30 @@ class Organization &lt; Profile
8 :display => %w[compact] 8 :display => %w[compact]
9 } 9 }
10 10
11 - scope :visible_for_person, lambda { |person|  
12 - joins('LEFT JOIN "role_assignments" ON "role_assignments"."resource_id" = "profiles"."id" AND "role_assignments"."resource_type" = \'Profile\'') 11 + # An Organization is considered visible to a given person if one of the
  12 +# following conditions are met:
  13 +# 1) The user is an environment administrator.
  14 +# 2) The user is an administrator of the organization.
  15 +# 3) The user is a member of the organization and the organization is
  16 +# visible.
  17 +# 4) The user is not a member of the organization but the organization is
  18 +# visible, public and enabled.
  19 + def self.visible_for_person(person)
  20 + joins('LEFT JOIN "role_assignments" ON ("role_assignments"."resource_id" = "profiles"."id"
  21 + AND "role_assignments"."resource_type" = \'Profile\') OR (
  22 + "role_assignments"."resource_id" = "profiles"."environment_id" AND
  23 + "role_assignments"."resource_type" = \'Environment\' )')
  24 + .joins('LEFT JOIN "roles" ON "role_assignments"."role_id" = "roles"."id"')
13 .where( 25 .where(
14 - ['( ( role_assignments.accessor_type = ? AND role_assignments.accessor_id = ? ) OR  
15 - (profiles.public_profile = ?)) AND (profiles.visible = ?)', Profile.name, person.id, true, true] 26 + ['( (roles.key = ? OR roles.key = ?) AND role_assignments.accessor_type = ? AND role_assignments.accessor_id = ? )
  27 + OR
  28 + ( ( ( role_assignments.accessor_type = ? AND role_assignments.accessor_id = ? ) OR
  29 + ( profiles.public_profile = ? AND profiles.enabled = ? ) ) AND
  30 + ( profiles.visible = ? ) )',
  31 + 'profile_admin', 'environment_administrator', Profile.name, person.id,
  32 + Profile.name, person.id, true, true, true]
16 ).uniq 33 ).uniq
17 - } 34 + end
18 35
19 settings_items :closed, :type => :boolean, :default => false 36 settings_items :closed, :type => :boolean, :default => false
20 def closed? 37 def closed?
@@ -154,6 +171,12 @@ class Organization &lt; Profile @@ -154,6 +171,12 @@ class Organization &lt; Profile
154 ] 171 ]
155 end 172 end
156 173
  174 + def short_name chars = 40
  175 + s = self.display_name
  176 + s = super(chars) if s.blank?
  177 + s
  178 + end
  179 +
157 def notification_emails 180 def notification_emails
158 emails = [contact_email].select(&:present?) + admins.map(&:email) 181 emails = [contact_email].select(&:present?) + admins.map(&:email)
159 if emails.empty? 182 if emails.empty?
app/models/person.rb
1 # A person is the profile of an user holding all relationships with the rest of the system 1 # A person is the profile of an user holding all relationships with the rest of the system
2 class Person < Profile 2 class Person < Profile
3 3
4 - attr_accessible :organization, :contact_information, :sex, :birth_date, :cell_phone,  
5 - :comercial_phone, :jabber_id, :personal_website, :nationality, :address_reference,  
6 - :district, :schooling, :schooling_status, :formation, :custom_formation, :area_of_study, 4 + attr_accessible :organization, :contact_information, :sex, :birth_date, :cell_phone,
  5 + :comercial_phone, :jabber_id, :personal_website, :nationality, :address_reference,
  6 + :district, :schooling, :schooling_status, :formation, :custom_formation, :area_of_study,
7 :custom_area_of_study, :professional_activity, :organization_website, :following_articiles 7 :custom_area_of_study, :professional_activity, :organization_website, :following_articiles
8 8
9 SEARCH_FILTERS = { 9 SEARCH_FILTERS = {
@@ -45,13 +45,17 @@ roles] } @@ -45,13 +45,17 @@ roles] }
45 } 45 }
46 46
47 scope :visible_for_person, lambda { |person| 47 scope :visible_for_person, lambda { |person|
48 - joins('LEFT JOIN "friendships" ON "friendships"."friend_id" = "profiles"."id"')  
49 - .where(  
50 - ['( ( friendships.person_id = ? ) OR (profiles.public_profile = ?)) AND (profiles.visible = ?)', person.id, true, true]  
51 - ).uniq 48 + joins('LEFT JOIN "role_assignments" ON
  49 + "role_assignments"."resource_id" = "profiles"."environment_id" AND
  50 + "role_assignments"."resource_type" = \'Environment\'')
  51 + .joins('LEFT JOIN "roles" ON "role_assignments"."role_id" = "roles"."id"')
  52 + .joins('LEFT JOIN "friendships" ON "friendships"."friend_id" = "profiles"."id"')
  53 + .where(
  54 + ['( roles.key = ? AND role_assignments.accessor_type = ? AND role_assignments.accessor_id = ? ) OR (
  55 + ( ( friendships.person_id = ? ) OR (profiles.public_profile = ?)) AND (profiles.visible = ?) )', 'environment_administrator', Profile.name, person.id, person.id, true, true]
  56 + ).uniq
52 } 57 }
53 58
54 -  
55 def has_permission_with_admin?(permission, resource) 59 def has_permission_with_admin?(permission, resource)
56 return true if resource.blank? || resource.admins.include?(self) 60 return true if resource.blank? || resource.admins.include?(self)
57 return true if resource.kind_of?(Profile) && resource.environment.admins.include?(self) 61 return true if resource.kind_of?(Profile) && resource.environment.admins.include?(self)
app/models/product.rb
@@ -51,6 +51,25 @@ class Product &lt; ActiveRecord::Base @@ -51,6 +51,25 @@ class Product &lt; ActiveRecord::Base
51 {:joins => :product_category, :conditions => ['categories.path LIKE ?', "%#{category.slug}%"]} if category 51 {:joins => :product_category, :conditions => ['categories.path LIKE ?', "%#{category.slug}%"]} if category
52 } 52 }
53 53
  54 + scope :visible_for_person, lambda { |person|
  55 + joins('INNER JOIN "profiles" enterprises ON enterprises."id" = "products"."profile_id"')
  56 + .joins('LEFT JOIN "role_assignments" ON ("role_assignments"."resource_id" = enterprises."id"
  57 + AND "role_assignments"."resource_type" = \'Profile\') OR (
  58 + "role_assignments"."resource_id" = enterprises."environment_id" AND
  59 + "role_assignments"."resource_type" = \'Environment\' )')
  60 + .joins('LEFT JOIN "roles" ON "role_assignments"."role_id" = "roles"."id"')
  61 + .where(
  62 + ['( (roles.key = ? OR roles.key = ?) AND role_assignments.accessor_type = \'Profile\' AND role_assignments.accessor_id = ? )
  63 + OR
  64 + ( ( ( role_assignments.accessor_type = \'Profile\' AND
  65 + role_assignments.accessor_id = ? ) OR
  66 + ( enterprises.public_profile = ? AND enterprises.enabled = ? ) ) AND
  67 + ( enterprises.visible = ? ) )',
  68 + 'profile_admin', 'environment_administrator', person.id, person.id,
  69 + true, true, true]
  70 + ).uniq
  71 + }
  72 +
54 after_update :save_image 73 after_update :save_image
55 74
56 def lat 75 def lat
app/models/profile.rb
@@ -128,15 +128,49 @@ class Profile &lt; ActiveRecord::Base @@ -128,15 +128,49 @@ class Profile &lt; ActiveRecord::Base
128 } 128 }
129 scope :no_templates, {:conditions => {:is_template => false}} 129 scope :no_templates, {:conditions => {:is_template => false}}
130 130
131 - #FIXME make this test  
132 - scope :newer_than, lambda { |reference_id|  
133 - {:conditions => ["profiles.id > #{reference_id}"]}  
134 - } 131 + # Returns a scoped object to select profiles in a given location or in a radius
  132 + # distance from the given location center.
  133 + # The parameter can be the `request.params` with the keys:
  134 + # * `country`: Country code string.
  135 + # * `state`: Second-level administrative country subdivisions.
  136 + # * `city`: City full name for center definition, or as set by users.
  137 + # * `lat`: The latitude to define the center of georef search.
  138 + # * `lng`: The longitude to define the center of georef search.
  139 + # * `distance`: Define the search radius in kilometers.
  140 + # NOTE: This method may return an exception object, to inform filter error.
  141 + # When chaining scopes, is hardly recommended you to add this as the last one,
  142 + # if you can't be sure about the provided parameters.
  143 + def self.by_location(params)
  144 + params = params.with_indifferent_access
  145 + if params[:distance].blank?
  146 + where_code = []
  147 + [ :city, :state, :country ].each do |place|
  148 + unless params[place].blank?
  149 + # ... So we must to find on this named location
  150 + # TODO: convert location attrs to a table collumn
  151 + where_code << "(profiles.data like '%#{place}: #{params[place]}%')"
  152 + end
  153 + end
  154 + self.where where_code.join(' AND ')
  155 + else # Filter in a georef circle
  156 + unless params[:lat].blank? && params[:lng].blank?
  157 + lat, lng = [ params[:lat].to_f, params[:lng].to_f ]
  158 + end
  159 + if !lat
  160 + location = [ params[:city], params[:state], params[:country] ].compact.join(', ')
  161 + if location.blank?
  162 + return Exception.new (
  163 + _('You must to provide `lat` and `lng`, or `city` and `country` to define the center of the search circle, defined by `distance`.')
  164 + )
  165 + end
  166 + lat, lng = Noosfero::GeoRef.location_to_georef location
  167 + end
  168 + dist = params[:distance].to_f
  169 + self.where "#{Noosfero::GeoRef.sql_dist lat, lng} <= #{dist}"
  170 + end
  171 + end
135 172
136 - #FIXME make this test  
137 - scope :older_than, lambda { |reference_id|  
138 - {:conditions => ["profiles.id < #{reference_id}"]}  
139 - } 173 + include TimeScopes
140 174
141 def members 175 def members
142 scopes = plugins.dispatch_scopes(:organization_members, self) 176 scopes = plugins.dispatch_scopes(:organization_members, self)
@@ -1006,19 +1040,11 @@ private :generate_url, :url_options @@ -1006,19 +1040,11 @@ private :generate_url, :url_options
1006 self.save 1040 self.save
1007 end 1041 end
1008 1042
1009 - def disabled?  
1010 - !visible  
1011 - end  
1012 -  
1013 def enable 1043 def enable
1014 self.visible = true 1044 self.visible = true
1015 self.save 1045 self.save
1016 end 1046 end
1017 1047
1018 - def enabled?  
1019 - visible  
1020 - end  
1021 -  
1022 def control_panel_settings_button 1048 def control_panel_settings_button
1023 {:title => _('Edit Profile'), :icon => 'edit-profile'} 1049 {:title => _('Edit Profile'), :icon => 'edit-profile'}
1024 end 1050 end
app/models/qualifier.rb
@@ -11,6 +11,12 @@ class Qualifier &lt; ActiveRecord::Base @@ -11,6 +11,12 @@ class Qualifier &lt; ActiveRecord::Base
11 has_many :qualifier_certifiers, :dependent => :destroy 11 has_many :qualifier_certifiers, :dependent => :destroy
12 has_many :certifiers, :through => :qualifier_certifiers 12 has_many :certifiers, :through => :qualifier_certifiers
13 13
  14 + def used_certs
  15 + Certifier.joins('INNER JOIN product_qualifiers' +
  16 + ' ON certifiers.id = product_qualifiers.certifier_id')
  17 + .where(product_qualifiers: {qualifier_id: self.id})
  18 + end
  19 +
14 has_many :product_qualifiers, :dependent => :destroy 20 has_many :product_qualifiers, :dependent => :destroy
15 has_many :products, :through => :product_qualifiers, :source => :product 21 has_many :products, :through => :product_qualifiers, :source => :product
16 22
app/models/suggest_article.rb
@@ -41,6 +41,7 @@ class SuggestArticle &lt; Task @@ -41,6 +41,7 @@ class SuggestArticle &lt; Task
41 return type if type < Article 41 return type if type < Article
42 end 42 end
43 TinyMceArticle 43 TinyMceArticle
  44 + (article[:type] || 'TinyMceArticle').constantize
44 end 45 end
45 46
46 def perform 47 def perform
app/models/uploaded_file.rb
1 -require 'short_filename'  
2 -  
3 # Article type that handles uploaded files. 1 # Article type that handles uploaded files.
4 # 2 #
5 # Limitation: only file metadata are versioned. Only the latest version 3 # Limitation: only file metadata are versioned. Only the latest version
@@ -14,8 +12,6 @@ class UploadedFile &lt; Article @@ -14,8 +12,6 @@ class UploadedFile &lt; Article
14 12
15 track_actions :upload_image, :after_create, :keep_params => ["view_url", "thumbnail_path", "parent.url", "parent.name"], :if => Proc.new { |a| a.published? && a.image? && !a.parent.nil? && a.parent.gallery? }, :custom_target => :parent 13 track_actions :upload_image, :after_create, :keep_params => ["view_url", "thumbnail_path", "parent.url", "parent.name"], :if => Proc.new { |a| a.published? && a.image? && !a.parent.nil? && a.parent.gallery? }, :custom_target => :parent
16 14
17 - include ShortFilename  
18 -  
19 def title 15 def title
20 if self.name.present? then self.name else self.filename end 16 if self.name.present? then self.name else self.filename end
21 end 17 end
@@ -65,7 +61,7 @@ class UploadedFile &lt; Article @@ -65,7 +61,7 @@ class UploadedFile &lt; Article
65 # :min_size => 2.megabytes 61 # :min_size => 2.megabytes
66 # :max_size => 5.megabytes 62 # :max_size => 5.megabytes
67 has_attachment :storage => :file_system, 63 has_attachment :storage => :file_system,
68 - :thumbnails => { :icon => [24,24], :thumb => '130x130>', :slideshow => '320x240>', :display => '640X480>' }, 64 + :thumbnails => { :icon => [24,24], :bigicon => [50,50], :thumb => '130x130>', :slideshow => '320x240>', :display => '640X480>' },
69 :thumbnail_class => Thumbnail, 65 :thumbnail_class => Thumbnail,
70 :max_size => self.max_size 66 :max_size => self.max_size
71 67
app/models/user.rb
@@ -34,6 +34,14 @@ class User &lt; ActiveRecord::Base @@ -34,6 +34,14 @@ class User &lt; ActiveRecord::Base
34 alias_method_chain :human_attribute_name, :customization 34 alias_method_chain :human_attribute_name, :customization
35 end 35 end
36 36
  37 + def self.build(user_data, person_data, environment)
  38 + user = User.new(user_data)
  39 + user.terms_of_use = environment.terms_of_use
  40 + user.environment = environment
  41 + user.person_data = person_data
  42 + user
  43 + end
  44 +
37 before_create do |user| 45 before_create do |user|
38 if user.environment.nil? 46 if user.environment.nil?
39 user.environment = Environment.default 47 user.environment = Environment.default
@@ -120,17 +128,15 @@ class User &lt; ActiveRecord::Base @@ -120,17 +128,15 @@ class User &lt; ActiveRecord::Base
120 self.update_attribute :last_login_at, Time.now 128 self.update_attribute :last_login_at, Time.now
121 end 129 end
122 130
123 - #FIXME make this test  
124 def generate_private_token! 131 def generate_private_token!
125 self.private_token = SecureRandom.hex 132 self.private_token = SecureRandom.hex
126 self.private_token_generated_at = DateTime.now 133 self.private_token_generated_at = DateTime.now
127 save(:validate => false) 134 save(:validate => false)
128 end 135 end
129 136
130 - #FIXME make this test  
131 - def private_token_expired?  
132 - return true if self.private_token_generated_at.nil?  
133 - self.generate_private_token! if self.private_token.nil? || (self.private_token_generated_at + 2.weeks < DateTime.now) 137 + TOKEN_VALIDITY = 2.weeks
  138 + def private_token_expired?
  139 + self.private_token.nil? || (self.private_token_generated_at + TOKEN_VALIDITY < DateTime.now)
134 end 140 end
135 141
136 # Activates the user in the database. 142 # Activates the user in the database.
@@ -334,6 +340,8 @@ class User &lt; ActiveRecord::Base @@ -334,6 +340,8 @@ class User &lt; ActiveRecord::Base
334 340
335 { 341 {
336 'login' => self.login, 342 'login' => self.login,
  343 + 'name' => self.person.name,
  344 + 'email' => self.email,
337 'avatar' => self.person.profile_custom_icon(gravatar_default), 345 'avatar' => self.person.profile_custom_icon(gravatar_default),
338 'is_admin' => self.person.is_admin?, 346 'is_admin' => self.person.is_admin?,
339 'since_month' => self.person.created_at.month, 347 'since_month' => self.person.created_at.month,
app/presenters/image.rb
@@ -4,6 +4,10 @@ class FilePresenter::Image &lt; FilePresenter @@ -4,6 +4,10 @@ class FilePresenter::Image &lt; FilePresenter
4 f.image? ? 10 : nil 4 f.image? ? 10 : nil
5 end 5 end
6 6
  7 + def sized_icon(size)
  8 + public_filename size
  9 + end
  10 +
7 def icon_name 11 def icon_name
8 public_filename :icon 12 public_filename :icon
9 end 13 end
app/views/admin_panel/_site_info.html.erb
@@ -3,6 +3,21 @@ @@ -3,6 +3,21 @@
3 <%= labelled_form_field(_('No reply email'), text_field(:environment, :noreply_email)) %> 3 <%= labelled_form_field(_('No reply email'), text_field(:environment, :noreply_email)) %>
4 <% themes_options = Theme.system_themes.map {|theme| [theme.name, theme.id] }.sort %> 4 <% themes_options = Theme.system_themes.map {|theme| [theme.name, theme.id] }.sort %>
5 <%= labelled_form_field(_('Theme'), select(:environment, :theme, options_for_select(themes_options, environment.theme))) %> 5 <%= labelled_form_field(_('Theme'), select(:environment, :theme, options_for_select(themes_options, environment.theme))) %>
  6 +
  7 +<%= labelled_form_field(
  8 + _("Article's date format"),
  9 + select(:environment, :date_format,
  10 + options_for_select([
  11 + [ _('mm/dd/yyyy'), 'numbers_with_year'],
  12 + [ _('mm/dd'), 'numbers'],
  13 + [ _('Month dd, yyyy'), 'month_name_with_year'],
  14 + [ _('Month dd'), 'month_name'],
  15 + [ _('X minutes/hours/days/months/years ago'), 'past_time']
  16 + ], environment.date_format
  17 + )
  18 + )
  19 +) %>
  20 +
6 <%= required f.text_field(:reports_lower_bound, :size => 3) %> 21 <%= required f.text_field(:reports_lower_bound, :size => 3) %>
7 <%= labelled_form_field(_('Default language'), select(:environment, :default_language, environment.locales.invert, { :selected => environment.default_locale, :include_blank => true })) %> 22 <%= labelled_form_field(_('Default language'), select(:environment, :default_language, environment.locales.invert, { :selected => environment.default_locale, :include_blank => true })) %>
8 <%= label_tag :languages, _('Available languages') %> 23 <%= label_tag :languages, _('Available languages') %>
app/views/api/index.html.erb 0 → 100644
@@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
  1 +<h1>EndPoints</h1>
  2 +
  3 +<div style="float: right">
  4 +<%= s_('api-playground|Try the %s') % link_to('API Playground', '/api/playground') %>
  5 +</div>
  6 +
  7 +<%= endpoints.map do |endpoint|
  8 + app = endpoint.options[:app].to_s
  9 + unless app.blank?
  10 + content_tag(:h2, app.split('::').last.to_s, title: app) +
  11 + (content_tag :ul do
  12 + endpoint.routes.map do |route|
  13 + content_tag :li do
  14 + content_tag(:strong, route.route_method) + ' ' +
  15 + route.route_path.gsub(':version', content_tag(:b, route.route_version))
  16 + end
  17 + end.join "\n"
  18 + end)
  19 + end
  20 +end.join "\n" %>
app/views/api/playground.html.erb 0 → 100644
@@ -0,0 +1,32 @@ @@ -0,0 +1,32 @@
  1 +<h1>API Playground</h1>
  2 +
  3 +<script>
  4 +var endpoints = <%=
  5 +endpoints.map do |endpoint|
  6 + app = endpoint.options[:app].to_s
  7 + unless app.blank?
  8 + endpoint.routes.map do |route|
  9 + {
  10 + method: route.route_method,
  11 + path: route.route_path.gsub(':version', route.route_version).split('(').first
  12 + }
  13 + end
  14 + end
  15 +end.flatten.compact.sort{|a,b| a[:path]=='/api/v1/login' ? -1:1}.to_json %>;
  16 +</script>
  17 +
  18 +<form id="api-form">
  19 + <label id="endpoint">Endpoint:
  20 + <select name="endpoint" onchange="playground.selEndpoint()"></select>
  21 + </label>
  22 + <label id="api-token">Token:
  23 + <%= tag :input, size: 32, placeholder: _('Use the login endpoint') %>
  24 + </label>
  25 +</form>
  26 +<div id="playground-ctrl">
  27 + <button onclick="playground.addFormParam()"><%=_('Add parameter')%></button>
  28 + <button onclick="playground.run()" style="font-weight:bold">&nbsp; <%=_('Run')%> &nbsp;</button>
  29 +</div>
  30 +<pre id="api-response" class="empty"></pre>
  31 +
  32 +<script src="/javascripts/api-playground.js"></script>
app/views/cms/_blog.html.erb
@@ -67,7 +67,8 @@ @@ -67,7 +67,8 @@
67 <%= labelled_form_field(_('How to display posts:'), f.select(:visualization_format, [ 67 <%= labelled_form_field(_('How to display posts:'), f.select(:visualization_format, [
68 [ _('Full post'), 'full'], 68 [ _('Full post'), 'full'],
69 [ _('First paragraph'), 'short'], 69 [ _('First paragraph'), 'short'],
70 - [ _('First paragraph, with post picture'), 'short+pic'] 70 + [ _('First paragraph, with post picture'), 'short+pic'],
  71 + [ _("Title, Image, Lead"), 'compact']
71 ])) %> 72 ])) %>
72 73
73 <%= labelled_form_field(_('Posts per page:'), f.select(:posts_per_page, Blog.posts_per_page_options)) %> 74 <%= labelled_form_field(_('Posts per page:'), f.select(:posts_per_page, Blog.posts_per_page_options)) %>
app/views/cms/_view_items.html.erb 0 → 100644
@@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
  1 +<% @articles.each do |article| article = FilePresenter.for article %>
  2 + <tr title="<%= article.title%>" >
  3 + <td class="article-name">
  4 + <%= link_to_article(article) %>
  5 + </td>
  6 + <% short_description = article.respond_to?(:short_description) ?
  7 + article.short_description :
  8 + article.class.short_description %>
  9 + <td class="article-mime" title=<%= short_description.to_json %>>
  10 + <%= short_description %>
  11 + </td>
  12 + <td class="last-update">
  13 + <%= time_ago_in_words article.updated_at %>
  14 + </td>
  15 + <td class="article-controls">
  16 + <%= expirable_button article, :edit, _('Edit'), {:action => 'edit', :id => article.id} if !remove_content_button(:edit, article) %>
  17 + <%= button_without_text :eyes, _('Public view'), article.view_url %>
  18 + <%= display_spread_button(article) unless remove_content_button(:spread, article) %>
  19 + <% if user.can_change_homepage? && !remove_content_button(:home, article) %>
  20 + <% if profile.home_page != article %>
  21 + <%= expirable_button article, :home, _('Use as homepage'), { :action => 'set_home_page', :id => article.id }, :method => :post %>
  22 + <% else %>
  23 + <%= button_without_text(:'home-not', _('Reset homepage'), { :action => 'set_home_page', :id => nil }, :method => :post) %>
  24 + <% end %>
  25 + <% end %>
  26 + <%= display_delete_button(article) if !remove_content_button(:delete, article) %>
  27 + </td>
  28 + </tr>
  29 +<% end %>
app/views/cms/view.html.erb
@@ -37,6 +37,7 @@ @@ -37,6 +37,7 @@
37 <tr> 37 <tr>
38 <th><%= _('Name') %></th> 38 <th><%= _('Name') %></th>
39 <th><%= _('Type') %></th> 39 <th><%= _('Type') %></th>
  40 + <th><%= _('Last update') %></th>
40 <th><%= _('Actions') %></th> 41 <th><%= _('Actions') %></th>
41 </tr> 42 </tr>
42 43
@@ -54,32 +55,7 @@ @@ -54,32 +55,7 @@
54 </tr> 55 </tr>
55 <% end %> 56 <% end %>
56 57
57 - <% @articles.each do |article| article = FilePresenter.for article %>  
58 - <tr title="<%= article.title%>" >  
59 - <td class="article-name">  
60 - <%= link_to_article(article) %>  
61 - </td>  
62 - <% short_description = article.respond_to?(:short_description) ?  
63 - article.short_description :  
64 - article.class.short_description %>  
65 - <td class="article-mime" title=<%= short_description.to_json %>>  
66 - <%= short_description %>  
67 - </td>  
68 - <td class="article-controls">  
69 - <%= expirable_button article, :edit, _('Edit'), {:action => 'edit', :id => article.id} if !remove_content_button(:edit, article) %>  
70 - <%= button_without_text :eyes, _('Public view'), article.view_url %>  
71 - <%= display_spread_button(article) unless remove_content_button(:spread, article) %>  
72 - <% if user.can_change_homepage? && !remove_content_button(:home, article) %>  
73 - <% if profile.home_page != article %>  
74 - <%= expirable_button article, :home, _('Use as homepage'), { :action => 'set_home_page', :id => article.id }, :method => :post %>  
75 - <% else %>  
76 - <%= button_without_text(:'home-not', _('Reset homepage'), { :action => 'set_home_page', :id => nil }, :method => :post) %>  
77 - <% end %>  
78 - <% end %>  
79 - <%= display_delete_button(article) if !remove_content_button(:delete, article) %>  
80 - </td>  
81 - </tr>  
82 - <% end %> 58 + <%= render 'view_items' %>
83 59
84 </table> 60 </table>
85 61
app/views/content_viewer/_article_title.html.erb 0 → 100644
@@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
  1 +<% if @page.belongs_to_blog? || @page.belongs_to_forum?%>
  2 + <h1 class="title">
  3 + <% if no_link %>
  4 + <%= h(@page.title) %>
  5 + <% else %>
  6 + <%= link_to(@page.name, @page.url) %>
  7 + <% end %>
  8 + </h1>
  9 + <%= render :partial => "publishing_info" %>
  10 + <% unless @page.abstract.blank? %>
  11 + <div class="preview">
  12 + <%= @page.lead %>
  13 + </div>
  14 + <% end %>
  15 +<% else %>
  16 + <h1 class="title">
  17 + <%= h(@page.title) %>
  18 + </h1>
  19 + <%= render :partial => "publishing_info" %>
  20 +<% end %>
app/views/content_viewer/_article_toolbar.html.erb
@@ -64,7 +64,7 @@ @@ -64,7 +64,7 @@
64 <% end %> 64 <% end %>
65 <%= link_to(image_tag('/images/icons-mime/rss-feed.png'), @page.feed.url, :class => 'blog-feed-link') if @page.has_posts? && @page.feed %> 65 <%= link_to(image_tag('/images/icons-mime/rss-feed.png'), @page.feed.url, :class => 'blog-feed-link') if @page.has_posts? && @page.feed %>
66 <%= @plugins.dispatch(:article_header_extra_contents, @page).collect { |content| instance_exec(&content) }.join("") %> 66 <%= @plugins.dispatch(:article_header_extra_contents, @page).collect { |content| instance_exec(&content) }.join("") %>
67 - <%= article_title(@page, :no_link => true) %> 67 + <%= render :partial => 'article_title', :locals => {:no_link => true} %>
68 <%= article_translations(@page) %> 68 <%= article_translations(@page) %>
69 </div> 69 </div>
70 </div> 70 </div>
app/views/content_viewer/_display_compact_format.html.erb 0 → 100644
@@ -0,0 +1,21 @@ @@ -0,0 +1,21 @@
  1 +<% if article.image %>
  2 + <% className = "article-compact-abstract-with-image" %>
  3 + <% if article.image.thumbnails_processed? %>
  4 + <% image_file = article.image.public_filename(:big) %>
  5 + <% else %>
  6 + <% image_file = "/images/icons-app/image-loading-thumb.png" %>
  7 + <% end %>
  8 +<% else %>
  9 + <% className = "article-compact-abstract" %>
  10 +<% end %>
  11 +
  12 +<div>
  13 + <% if article.image %>
  14 + <div class = "article-compact-image">
  15 + <%= image_tag(image_file) %>
  16 + </div>
  17 + <% end %>
  18 + <div class = <%= className %> >
  19 + <%= article.lead(400) %>
  20 + </div>
  21 +</div>
app/views/content_viewer/_publishing_info.html.erb 0 → 100644
@@ -0,0 +1,29 @@ @@ -0,0 +1,29 @@
  1 +<span class="publishing-info">
  2 + <span class="date">
  3 + <%= show_date(@page.published_at) %>
  4 + </span>
  5 + <span class="author">
  6 + <%= _(", by %s") % (@page.author ? link_to(@page.author_name, @page.author_url) : @page.author_name) %>
  7 + </span>
  8 +<% unless @no_comments %>
  9 + <span class="comments">
  10 + <%= (" - %s") % link_to_comments(@page)%>
  11 + </span>
  12 +<% end %>
  13 +</span>
  14 +
  15 +<% if @page.display_hits? || @page.license.present? %>
  16 + <div id='article-sub-header'>
  17 + <% if @page.display_hits? %>
  18 + <div id="article-hits">
  19 + <%= n_('Viewed one time', 'Viewed %{num} times', @page.hits) % { :num => @page.hits } %>
  20 + </div>
  21 + <% end %>
  22 +
  23 + <% if @page.license.present? %>
  24 + <div id="article-license">
  25 + <%= _('Licensed under %s') % (@page.license.url.present? ? link_to(@page.license.name, @page.license.url, :target => '_blank') : @page.license.name) %>
  26 + </div>
  27 + <% end %>
  28 + </div>
  29 +<% end %>
app/views/content_viewer/blog_page.html.erb
@@ -8,7 +8,7 @@ @@ -8,7 +8,7 @@
8 </div> 8 </div>
9 </div> 9 </div>
10 <hr class="pre-posts"/> 10 <hr class="pre-posts"/>
11 -<div class="blog-posts"> 11 +<div class="blog-posts page-<%= @npage %>">
12 <% paginate = true %> 12 <% paginate = true %>
13 <%= 13 <%=
14 posts = @posts 14 posts = @posts
app/views/content_viewer/event_page.html.erb 0 → 100644
@@ -0,0 +1,41 @@ @@ -0,0 +1,41 @@
  1 +<div class="event-card">
  2 + <div class="event-image">
  3 + <% if event.image %>
  4 + <%= image_tag(event.image.public_filename(:big)) %>
  5 + <% end %>
  6 + </div>
  7 + <div class="about-event">
  8 + <% if event.start_date.present? || event.end_date.present? %>
  9 + <span class="event-date">
  10 + <%= show_period(event.start_date, event.end_date) %>
  11 + </span>
  12 + <% end %>
  13 + <% if event.link.present? %>
  14 + <span class="event-link">
  15 + <%= link_to event.link, event.link %>
  16 + </span>
  17 + <% end %>
  18 + <% if event.address.present? %>
  19 + <span class="event-address">
  20 + <span>
  21 + <%= event.address %>
  22 + </span>
  23 + </span>
  24 + <% end %>
  25 + </div>
  26 +</div>
  27 +
  28 +<div class="event-body">
  29 + <% if format == 'short' %>
  30 + <%= display_short_format event, :comments_link => false, :read_more_link => false %>
  31 + <% else %>
  32 + <% unless event.abstract.blank? %>
  33 + <div class="event-lead">
  34 + <%= event.article_lead %>
  35 + </div>
  36 + <% end %>
  37 + <div class="event-content">
  38 + <%= event.body %>
  39 + </div>
  40 + <% end %>
  41 +</div>
app/views/content_viewer/folder.html.erb
1 <% unless folder.body.blank? %> 1 <% unless folder.body.blank? %>
2 - <div> 2 + <div class="folder-description">
3 <%= folder.body %> 3 <%= folder.body %>
4 </div> 4 </div>
5 - <hr/>  
6 <% end %> 5 <% end %>
7 6
8 <% if folder.children.empty? %> 7 <% if folder.children.empty? %>
app/views/content_viewer/view_page.html.erb
@@ -24,22 +24,6 @@ @@ -24,22 +24,6 @@
24 <%= render :partial => 'article_toolbar' %> 24 <%= render :partial => 'article_toolbar' %>
25 </div> 25 </div>
26 26
27 -<% if @page.display_hits? || @page.license.present? %>  
28 - <div id='article-sub-header'>  
29 - <% if @page.display_hits? %>  
30 - <div id="article-hits">  
31 - <%= n_('Viewed one time', 'Viewed %{num} times', @page.hits) % { :num => @page.hits } %>  
32 - </div>  
33 - <% end %>  
34 -  
35 - <% if @page.license.present? %>  
36 - <div id="article-license">  
37 - <%= _('Licensed under %s') % (@page.license.url.present? ? link_to(@page.license.name, @page.license.url, :target => '_blank') : @page.license.name) %>  
38 - </div>  
39 - <% end %>  
40 - </div>  
41 -<% end %>  
42 -  
43 <% if NOOSFERO_CONF['addthis_enabled'] %> 27 <% if NOOSFERO_CONF['addthis_enabled'] %>
44 <%= render :partial => 'addthis' %> 28 <%= render :partial => 'addthis' %>
45 <% end %> 29 <% end %>
@@ -47,6 +31,12 @@ @@ -47,6 +31,12 @@
47 <% cache(@page.cache_key(params, user, language)) do %> 31 <% cache(@page.cache_key(params, user, language)) do %>
48 <div class="<%="article-body article-body-" + @page.css_class_name %>"> 32 <div class="<%="article-body article-body-" + @page.css_class_name %>">
49 <% options = @page.image? ? {:gallery_view => true} : {} %> 33 <% options = @page.image? ? {:gallery_view => true} : {} %>
  34 + <% if @page.image.present? && !@page.event? %>
  35 + <div class="article-body-img">
  36 + <%= image_tag(@page.image.public_filename) %>
  37 + <p><%= @page.image.label%></p>
  38 + </div>
  39 + <% end %>
50 <%= article_to_html(@page, options) %> 40 <%= article_to_html(@page, options) %>
51 <br style="clear:both" /> 41 <br style="clear:both" />
52 </div> <!-- end class="article-body" --> 42 </div> <!-- end class="article-body" -->
app/views/layouts/application-ng.html.erb
@@ -27,6 +27,7 @@ @@ -27,6 +27,7 @@
27 27
28 <script type="text/javascript"> 28 <script type="text/javascript">
29 DEFAULT_LOADING_MESSAGE = <%="'#{ _('loading...') }'" %>; 29 DEFAULT_LOADING_MESSAGE = <%="'#{ _('loading...') }'" %>;
  30 + noosfero.profile = <%= (@profile.identifier if @profile).to_json %>
30 </script> 31 </script>
31 32
32 </head> 33 </head>
app/views/manage_products/_categories_autocomplete.html.erb 0 → 100644
@@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
  1 +<%= text_field_tag 'product_category_id', '', :placeholder => _('type a category for the product') %>
  2 +
  3 +<%= javascript_include_tag '/javascripts/product_categories.js' %>
  4 +<%= javascript_tag do %>
  5 + product_categories.autocomplete.search_url = <%= url_for(:controller => :manage_products, :action => :search_categories).to_json %>
  6 + product_categories.autocomplete.select_url = <%= url_for(:controller => :manage_products, :action => :show_category_tree).to_json %>
  7 + product_categories.autocomplete.load('#product_category_id')
  8 +<% end %>
app/views/manage_products/_selected_category_tree.html.erb 0 → 100644
@@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
  1 +<%= categories_container selects_for_all_ancestors(@category), hierarchy_category_navigation(@category, :make_links => true) %>
  2 +
app/views/manage_products/edit_category.html.erb
@@ -16,7 +16,7 @@ @@ -16,7 +16,7 @@
16 16
17 <h3><%= _('Edit category of this product:') %></h3> 17 <h3><%= _('Edit category of this product:') %></h3>
18 18
19 - <%= categories_container(selects_for_all_ancestors(@category), hierarchy_category_navigation(@category, :make_links => true)) %> 19 + <%= render 'manage_products/selected_category_tree' %>
20 20
21 <div id='categories_selection_actionbar'> 21 <div id='categories_selection_actionbar'>
22 <%= button(:back, _('Back to product'), :action => 'show', :id => @product) %> 22 <%= button(:back, _('Back to product'), :action => 'show', :id => @product) %>
app/views/person_notifier/mailer/_comment.html.erb
@@ -19,7 +19,7 @@ @@ -19,7 +19,7 @@
19 <span style="font-size: 12px;"><%= comment.title %></span><br/> 19 <span style="font-size: 12px;"><%= comment.title %></span><br/>
20 <% end %> 20 <% end %>
21 <span style="font-size: 10px;"><%= txt2html comment.body %></span><br/> 21 <span style="font-size: 10px;"><%= txt2html comment.body %></span><br/>
22 - <span style="font-size: 8px; color: #929292"><%= time_ago_as_sentence(comment.created_at) %></span> 22 + <span style="font-size: 8px; color: #929292"><%= time_ago_in_words(comment.created_at) %></span>
23 <br style="clear: both;" /> 23 <br style="clear: both;" />
24 24
25 <% unless comment.replies.blank? %> 25 <% unless comment.replies.blank? %>
app/views/person_notifier/mailer/_create_article.html.erb
@@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
6 <p> 6 <p>
7 <span style="font-size: 14px;"><%= link_to activity.user.short_name(20), activity.user.url %></span> 7 <span style="font-size: 14px;"><%= link_to activity.user.short_name(20), activity.user.url %></span>
8 <span style="font-size: 14px;"><%= _("has published on community %s") % link_to(activity.target.profile.short_name(20), activity.target.profile.url, :style => "color: #333; font-weight: bold; text-decoration: none;") if activity.target.profile.is_a?(Community) %></span> 8 <span style="font-size: 14px;"><%= _("has published on community %s") % link_to(activity.target.profile.short_name(20), activity.target.profile.url, :style => "color: #333; font-weight: bold; text-decoration: none;") if activity.target.profile.is_a?(Community) %></span>
9 - <span style="font-size: 10px; color: #929292; float:right;"><%= time_ago_as_sentence(activity.created_at) %></span> 9 + <span style="font-size: 10px; color: #929292; float:right;"><%= time_ago_in_words(activity.created_at) %></span>
10 </p> 10 </p>
11 <p> 11 <p>
12 <span style="font-size: 14px;"><%= link_to(activity.params['name'], activity.params['url'], :style => "color: #333; font-weight: bold; text-decoration: none;") %></span> 12 <span style="font-size: 14px;"><%= link_to(activity.params['name'], activity.params['url'], :style => "color: #333; font-weight: bold; text-decoration: none;") %></span>
app/views/person_notifier/mailer/_default_activity.html.erb
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 <td> 5 <td>
6 <p> 6 <p>
7 <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span> 7 <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span>
8 - <span style="font-size: 10px; color: #929292; float: right;"><%= time_ago_as_sentence(activity.created_at) %></span> 8 + <span style="font-size: 10px; color: #929292; float: right;"><%= time_ago_in_words(activity.created_at) %></span>
9 </p> 9 </p>
10 </td> 10 </td>
11 </tr> 11 </tr>
app/views/person_notifier/mailer/_task.html.erb
@@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
12 <span style="font-size: 14px"> 12 <span style="font-size: 14px">
13 <%= task_information(task) %> 13 <%= task_information(task) %>
14 </span> 14 </span>
15 - <span style="font-size: 10px; color: #929292; float: right;"><%= time_ago_as_sentence(task.created_at) %></span> 15 + <span style="font-size: 10px; color: #929292; float: right;"><%= time_ago_in_words(task.created_at) %></span>
16 </div> 16 </div>
17 </td> 17 </td>
18 </tr> 18 </tr>
app/views/person_notifier/mailer/_upload_image.html.erb
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 <td> 5 <td>
6 <p> 6 <p>
7 <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span> 7 <span style="font-size: 14px;"><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></span>
8 - <span style="font-size: 10px; color: #929292; float:right;"><%= time_ago_as_sentence(activity.created_at) %></span> 8 + <span style="font-size: 10px; color: #929292; float:right;"><%= time_ago_in_words(activity.created_at) %></span>
9 </p> 9 </p>
10 </td> 10 </td>
11 </tr> 11 </tr>
app/views/profile/_comment.html.erb
@@ -40,7 +40,7 @@ @@ -40,7 +40,7 @@
40 <%= txt2html comment.body %> 40 <%= txt2html comment.body %>
41 </div> 41 </div>
42 <div class="profile-activity-time"> 42 <div class="profile-activity-time">
43 - <%= time_ago_as_sentence(comment.created_at) %> 43 + <%= time_ago_in_words(comment.created_at) %>
44 </div> 44 </div>
45 </div> 45 </div>
46 46
app/views/profile/_create_article.html.erb
@@ -12,7 +12,7 @@ @@ -12,7 +12,7 @@
12 <%= image_tag(activity.params['first_image']) unless activity.params['first_image'].blank? %><%= strip_tags(truncate(activity.params['lead'], :length => 1000, :ommision => '...')).gsub(/(\xC2\xA0|\s)+/, ' ').gsub(/^\s+/, '') unless activity.params['lead'].blank? %> <small><%= link_to(_('See more'), activity.params['url']) unless activity.get_lead.blank? %></small> 12 <%= image_tag(activity.params['first_image']) unless activity.params['first_image'].blank? %><%= strip_tags(truncate(activity.params['lead'], :length => 1000, :ommision => '...')).gsub(/(\xC2\xA0|\s)+/, ' ').gsub(/^\s+/, '') unless activity.params['lead'].blank? %> <small><%= link_to(_('See more'), activity.params['url']) unless activity.get_lead.blank? %></small>
13 </div> 13 </div>
14 <%= content_tag(:p, link_to(_('See complete forum'), activity.get_url), :class => 'see-forum') if activity.target.is_a?(Forum) %> 14 <%= content_tag(:p, link_to(_('See complete forum'), activity.get_url), :class => 'see-forum') if activity.target.is_a?(Forum) %>
15 - <p class='profile-activity-time'><%= time_ago_as_sentence(activity.created_at) %></p> 15 + <p class='profile-activity-time'><%= time_ago_in_words(activity.created_at) %></p>
16 <div class='profile-wall-actions'> 16 <div class='profile-wall-actions'>
17 <%= link_to s_('profile|Comment'), '#', { :class => 'focus-on-comment'} %> 17 <%= link_to s_('profile|Comment'), '#', { :class => 'focus-on-comment'} %>
18 <%= link_to_function(_('Remove'), 'remove_item_wall(this, \'%s\', \'%s\', \'%s\'); return false ;' % [".profile-activity-item", url_for(:profile => params[:profile], :action => :remove_activity, :activity_id => activity.id, :only_hide => true, :view => params[:view]), _('Are you sure you want to remove this activity and all its replies?')]) if logged_in? && current_person == @profile %> 18 <%= link_to_function(_('Remove'), 'remove_item_wall(this, \'%s\', \'%s\', \'%s\'); return false ;' % [".profile-activity-item", url_for(:profile => params[:profile], :action => :remove_activity, :activity_id => activity.id, :only_hide => true, :view => params[:view]), _('Are you sure you want to remove this activity and all its replies?')]) if logged_in? && current_person == @profile %>
app/views/profile/_default_activity.html.erb
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 </div> 3 </div>
4 <div class='profile-activity-description'> 4 <div class='profile-activity-description'>
5 <p class='profile-activity-text'><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></p> 5 <p class='profile-activity-text'><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></p>
6 - <p class='profile-activity-time'><%= time_ago_as_sentence(activity.created_at) %></p> 6 + <p class='profile-activity-time'><%= time_ago_in_words(activity.created_at) %></p>
7 <div class='profile-wall-actions'> 7 <div class='profile-wall-actions'>
8 <%= link_to s_('profile|Comment'), '#', { :class => 'focus-on-comment'} %> 8 <%= link_to s_('profile|Comment'), '#', { :class => 'focus-on-comment'} %>
9 <%= link_to_function(_('Remove'), 'remove_item_wall(this, \'%s\', \'%s\', \'%s\'); return false ;' % [".profile-activity-item", url_for(:profile => params[:profile], :action => :remove_activity, :activity_id => activity.id, :view => params[:view]), _('Are you sure you want to remove this activity and all its replies?')]) if logged_in? && current_person == @profile %> 9 <%= link_to_function(_('Remove'), 'remove_item_wall(this, \'%s\', \'%s\', \'%s\'); return false ;' % [".profile-activity-item", url_for(:profile => params[:profile], :action => :remove_activity, :activity_id => activity.id, :view => params[:view]), _('Are you sure you want to remove this activity and all its replies?')]) if logged_in? && current_person == @profile %>
app/views/profile/_leave_scrap.html.erb
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 </div> 3 </div>
4 <div class='profile-activity-description'> 4 <div class='profile-activity-description'>
5 <p class='profile-activity-text'><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></p> 5 <p class='profile-activity-text'><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></p>
6 - <p class='profile-activity-time'><%= time_ago_as_sentence(activity.created_at) %></p> 6 + <p class='profile-activity-time'><%= time_ago_in_words(activity.created_at) %></p>
7 <div class='profile-wall-actions'> 7 <div class='profile-wall-actions'>
8 <%= link_to_function(_('Remove'), 'remove_item_wall(this, \'%s\', \'%s\', \'%s\'); return false ;' % [".profile-activity-item", url_for(:profile => params[:profile], :action => :remove_activity, :activity_id => activity.id, :view => params[:view]), _('Are you sure you want to remove this activity and all its replies?')]) if logged_in? && current_person == @profile %> 8 <%= link_to_function(_('Remove'), 'remove_item_wall(this, \'%s\', \'%s\', \'%s\'); return false ;' % [".profile-activity-item", url_for(:profile => params[:profile], :action => :remove_activity, :activity_id => activity.id, :view => params[:view]), _('Are you sure you want to remove this activity and all its replies?')]) if logged_in? && current_person == @profile %>
9 </div> 9 </div>
app/views/profile/_profile_scrap.html.erb
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 <div class='profile-activity-description'> 5 <div class='profile-activity-description'>
6 <p class='profile-activity-sender'><%= link_to scrap.sender.name, scrap.sender.url %></p> 6 <p class='profile-activity-sender'><%= link_to scrap.sender.name, scrap.sender.url %></p>
7 <p class='profile-activity-text'><%= txt2html scrap.content %></p> 7 <p class='profile-activity-text'><%= txt2html scrap.content %></p>
8 - <p class='profile-activity-time'><%= time_ago_as_sentence(scrap.created_at) %></p> 8 + <p class='profile-activity-time'><%= time_ago_in_words(scrap.created_at) %></p>
9 <div class='profile-wall-actions'> 9 <div class='profile-wall-actions'>
10 <% if logged_in? && current_person.follows?(scrap.sender) %> 10 <% if logged_in? && current_person.follows?(scrap.sender) %>
11 <span class='profile-activity-send-reply'> 11 <span class='profile-activity-send-reply'>
@@ -22,5 +22,5 @@ @@ -22,5 +22,5 @@
22 <% end %> 22 <% end %>
23 </ul> 23 </ul>
24 <%= render :partial => 'profile_scrap_reply_form', :locals => { :scrap => scrap } %> 24 <%= render :partial => 'profile_scrap_reply_form', :locals => { :scrap => scrap } %>
25 - <hr /> 25 + <hr />
26 </li> 26 </li>
app/views/profile/_profile_scraps.html.erb
@@ -5,7 +5,7 @@ @@ -5,7 +5,7 @@
5 <div class='profile-activity-description'> 5 <div class='profile-activity-description'>
6 <p class='profile-activity-sender'><%= link_to scrap.sender.name, scrap.sender.url %></p> 6 <p class='profile-activity-sender'><%= link_to scrap.sender.name, scrap.sender.url %></p>
7 <p class='profile-activity-text'><%= txt2html scrap.content %></p> 7 <p class='profile-activity-text'><%= txt2html scrap.content %></p>
8 - <p class='profile-activity-time'><%= time_ago_as_sentence(scrap.created_at) %></p> 8 + <p class='profile-activity-time'><%= time_ago_in_words(scrap.created_at) %></p>
9 <div class='profile-wall-actions'> 9 <div class='profile-wall-actions'>
10 <% if logged_in? && current_person.follows?(scrap.sender) %> 10 <% if logged_in? && current_person.follows?(scrap.sender) %>
11 <span class='profile-activity-send-reply'> 11 <span class='profile-activity-send-reply'>
app/views/profile/_upload_image.html.erb
@@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
4 </div> 4 </div>
5 <div class='profile-activity-description'> 5 <div class='profile-activity-description'>
6 <p class='profile-activity-text'><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></p> 6 <p class='profile-activity-text'><%= link_to activity.user.name, activity.user.url %> <%= describe activity %></p>
7 - <p class='profile-activity-time'><%= time_ago_as_sentence(activity.created_at) %></p> 7 + <p class='profile-activity-time'><%= time_ago_in_words(activity.created_at) %></p>
8 <div class='profile-wall-actions'> 8 <div class='profile-wall-actions'>
9 <%= link_to_function(_('Remove'), 'remove_item_wall(this, \'%s\', \'%s\', \'%s\'); return false ;' % [".profile-activity-item", url_for(:profile => params[:profile], :action => :remove_activity, :activity_id => activity.id, :view => params[:view]), _('Are you sure you want to remove this activity and all its replies?')]) if logged_in? && current_person == @profile %> 9 <%= link_to_function(_('Remove'), 'remove_item_wall(this, \'%s\', \'%s\', \'%s\'); return false ;' % [".profile-activity-item", url_for(:profile => params[:profile], :action => :remove_activity, :activity_id => activity.id, :view => params[:view]), _('Are you sure you want to remove this activity and all its replies?')]) if logged_in? && current_person == @profile %>
10 </div> 10 </div>
app/views/shared/_change_image.html.erb
1 - <%= i.file_field( :uploaded_data, { :onchange => 'updateImg(this.value)' } ) %>  
2 - <%= button_to_function(:cancel,_('Cancel'),"jQuery('#change-image-link').show(); jQuery('#change-image').html('')", :id => 'cancel-change-image-link', :style => 'display: none')%> 1 +<%= i.file_field( :uploaded_data, { :onchange => 'updateImg(this.value)' } ) %>
  2 +<%= labelled_form_field(_("Image Label:"), i.text_field(:label)) %>
  3 +<%= button_to_function(:cancel,_('Cancel'),"jQuery('#change-image-link').show(); jQuery('#change-image').html('')", :id => 'cancel-change-image-link', :style => 'display: none')%>
app/views/shared/_content_item.html.erb 0 → 100644
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
  1 +<div id="list-item">
  2 + <div class="item-info">
  3 + <div class="item-icon" >
  4 + <%= display_content_icon(content) %>
  5 + </div>
  6 + <span class="item-description">
  7 + <%= link_to(content.name, content.url) %>
  8 + </span>
  9 + <span class="item-date"><%= _("Published at: #{show_date(content.updated_at)}") %></span>
  10 + </div>
  11 +</div>
app/views/shared/_lead_and_body.html.erb
@@ -19,17 +19,27 @@ @@ -19,17 +19,27 @@
19 19
20 <div class='article-lead' id="article-lead-<%=lead_id.to_s%>"> 20 <div class='article-lead' id="article-lead-<%=lead_id.to_s%>">
21 21
  22 + <% abstract_options = {:style => 'width: 100%; height: 200px;', :class => editor_type} %>
22 <% if f %> 23 <% if f %>
23 - <%= labelled_form_field(_(abstract_label), f.text_area(abstract_method, :style => 'width: 100%; height: 200px;', :class => editor_type)) %> 24 + <%= labelled_form_field(_(abstract_label), f.text_area(abstract_method, abstract_options)) %>
24 <% else %> 25 <% else %>
25 - <%= labelled_form_field(_(abstract_label), text_area(object, abstract_method, :style => 'width: 100%; height: 200px;', :class => editor_type)) %> 26 + <% if @article.kind_of?(Article) %>
  27 + <%= labelled_form_field(_(abstract_label), text_area_tag("article[abstract]", @escaped_abstract, abstract_options)) %>
  28 + <% else %>
  29 + <%= labelled_form_field(_(abstract_label), text_area(object, abstract_method, abstract_options)) %>
  30 + <% end %>
26 <% end %> 31 <% end %>
27 </div> 32 </div>
28 <div style="margin-top: 10px;"> 33 <div style="margin-top: 10px;">
  34 + <% body_options = {:style => 'width: 100%; height: 400px;', :class => editor_type} %>
29 <% if f %> 35 <% if f %>
30 - <%= labelled_form_field(_(body_label), f.text_area(body_method, :style => 'width: 100%; height: 400px;', :class => editor_type)) %> 36 + <%= labelled_form_field(_(body_label), f.text_area(body_method, body_options)) %>
31 <% else %> 37 <% else %>
32 - <%= labelled_form_field(_(body_label), text_area(object, body_method, :style => 'width: 100%; height: 400px;', :class => editor_type)) %> 38 + <% if @article.kind_of?(Article) %>
  39 + <%= labelled_form_field(_(body_label), text_area_tag("article[body]", @escaped_body, body_options)) %>
  40 + <% else %>
  41 + <%= labelled_form_field(_(body_label), text_area(object, body_method, body_options)) %>
  42 + <% end %>
33 <% end %> 43 <% end %>
34 </div> 44 </div>
35 45
app/views/shared/content_list.html.erb
1 -<table class="<%= list_type %>-content">  
2 - <tr>  
3 - <th><%= _('Title') %></th>  
4 - <th><%= _('Last update') %></th>  
5 - </tr> 1 +<ul class="<%= list_type %>-content">
6 <% contents.each do |content| %> 2 <% contents.each do |content| %>
7 - <% if content.display_to?(user) %>  
8 - <%= display_content_in_listing :content=>content, :list_type=>list_type, :recursive=>recursive %>  
9 - <% end %> 3 + <li class="<%= list_type %>-item">
  4 + <% if content.display_to?(user) %>
  5 + <%= render :partial => 'shared/content_item', :locals => { :content => content } %>
  6 + <% end %>
  7 + </li>
10 <% end %> 8 <% end %>
11 -</table> 9 +</ul>
12 10
13 <p><%= pagination_links contents, :param_name => 'npage', :page_links => true %></p> 11 <p><%= pagination_links contents, :param_name => 'npage', :page_links => true %></p>
app/views/tasks/_abuse_complaint_accept_details.html.erb
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 <% task.abuse_reports.each do |abuse_report| %> 2 <% task.abuse_reports.each do |abuse_report| %>
3 <div> 3 <div>
4 <strong style="word-wrap: break-word; display: block; padding-right: 40px">"<%= abuse_report.reason %>"</strong> <br /> 4 <strong style="word-wrap: break-word; display: block; padding-right: 40px">"<%= abuse_report.reason %>"</strong> <br />
5 - <i><%= _('Reported by %{reporter} %{time}.') % {:reporter => abuse_report.reporter.name, :time => time_ago_as_sentence(abuse_report.created_at) }%></i> <br /> 5 + <i><%= _('Reported by %{reporter} %{time}.') % {:reporter => abuse_report.reporter.name, :time => time_ago_in_words(abuse_report.created_at) }%></i> <br />
6 <% if !abuse_report.content.blank? %> 6 <% if !abuse_report.content.blank? %>
7 <button class="display-abuse-report-details" data-report="<%=abuse_report.id%>"><%=_('View details')%></button> 7 <button class="display-abuse-report-details" data-report="<%=abuse_report.id%>"><%=_('View details')%></button>
8 <div style='display: none' id=<%= 'abuse-report-details-'+abuse_report.id.to_s %> class="abuse-report-details"> 8 <div style='display: none' id=<%= 'abuse-report-details-'+abuse_report.id.to_s %> class="abuse-report-details">
app/views/tasks/_suggest_article_accept_details.html.erb
@@ -14,6 +14,5 @@ @@ -14,6 +14,5 @@
14 <%= labelled_form_field(_('Highlight this article'), a.check_box(:highlighted)) %> 14 <%= labelled_form_field(_('Highlight this article'), a.check_box(:highlighted)) %>
15 15
16 <%= a.hidden_field(:type) %> 16 <%= a.hidden_field(:type) %>
17 -  
18 <%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true, :f => a, :lead_id => task.id} %> 17 <%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true, :f => a, :lead_id => task.id} %>
19 <% end %> 18 <% end %>
config/application.rb
@@ -138,7 +138,7 @@ module Noosfero @@ -138,7 +138,7 @@ module Noosfero
138 config.middleware.use Rack::Cors do 138 config.middleware.use Rack::Cors do
139 allow do 139 allow do
140 origins '*' 140 origins '*'
141 - resource 'api/*', :headers => :any, :methods => [:get, :post] 141 + resource '/api/*', :headers => :any, :methods => [:get, :post]
142 end 142 end
143 end 143 end
144 144
config/database.yml.gitlab-ci 0 → 100644
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 +test: &TEST
  2 + adapter: postgresql
  3 + database: gitlab_ci_test
  4 + username: gitlab_ci_runner
  5 +development:
  6 + <<: *TEST
config/database.yml.travis 0 → 100644
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +# From http://about.travis-ci.org/docs/user/database-setup/
  2 +test:
  3 + adapter: postgresql
  4 + database: myapp_test
  5 + username: postgres
config/environments/staging.rb 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +# inherit from production
  2 +require_relative 'production'
  3 +
  4 +Noosfero::Application.configure do
  5 +
  6 + # expose errors
  7 + config.consider_all_requests_local = true
  8 +
  9 + # ease debug
  10 + config.assets.compress = false
  11 +
  12 +end
  13 +
config/initializers/noosfero_extensions.rb
1 require 'noosfero/role_assignment_ext' 1 require 'noosfero/role_assignment_ext'
2 require 'noosfero/action_tracker_ext' 2 require 'noosfero/action_tracker_ext'
  3 +require 'noosfero/vote_ext'
config/noosfero.yml.dist
@@ -11,6 +11,9 @@ development: @@ -11,6 +11,9 @@ development:
11 max_upload_size: 5MB 11 max_upload_size: 5MB
12 hours_until_user_activation_check: 72 12 hours_until_user_activation_check: 72
13 exclude_profile_identifier_pattern: index(\..*)?|home(\..*)? 13 exclude_profile_identifier_pattern: index(\..*)?|home(\..*)?
  14 + api_recaptcha_site_key: '6LdsWAcTAAAAAChTUUD6yu9fCDhdIZzNd7F53zf-'
  15 + api_recaptcha_private_key: '6LdsWAcTAAAAAB6maB_HalVyCc4asDAxPxloIMvY'
  16 + api_recaptcha_verify_uri: 'https://www.google.com/recaptcha/api/siteverify'
14 17
15 #Google Recaptcha setup 18 #Google Recaptcha setup
16 api_captcha_enabled: true 19 api_captcha_enabled: true
config/routes.rb
@@ -22,6 +22,7 @@ Noosfero::Application.routes.draw do @@ -22,6 +22,7 @@ Noosfero::Application.routes.draw do
22 root :to => 'home#index', :constraints => EnvironmentDomainConstraint.new 22 root :to => 'home#index', :constraints => EnvironmentDomainConstraint.new
23 23
24 match 'site(/:action)', :controller => 'home' 24 match 'site(/:action)', :controller => 'home'
  25 + match 'api(/:action)', :controller => 'api'
25 26
26 match 'images(/*stuff)' => 'not_found#nothing' 27 match 'images(/*stuff)' => 'not_found#nothing'
27 match 'stylesheets(/*stuff)' => 'not_found#nothing' 28 match 'stylesheets(/*stuff)' => 'not_found#nothing'
db/migrate/20140407013817_add_private_token_info_to_users.rb
@@ -1,11 +0,0 @@ @@ -1,11 +0,0 @@
1 -class AddPrivateTokenInfoToUsers < ActiveRecord::Migration  
2 - def self.up  
3 - add_column :users, :private_token, :string  
4 - add_column :users, :private_token_generated_at, :datetime  
5 - end  
6 -  
7 - def self.down  
8 - remove_column :users, :private_token  
9 - remove_column :users, :private_token_generated_at  
10 - end  
11 -end  
db/migrate/20140708123314_index_role_assignments_filtered_fields.rb 0 → 100644
@@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
  1 +class IndexRoleAssignmentsFilteredFields < ActiveRecord::Migration
  2 +
  3 + def self.up
  4 + add_index :role_assignments, [:accessor_id, :accessor_type]
  5 + add_index :role_assignments, [:accessor_id, :accessor_type, :role_id], name: :index_on_role_assigments_accessor_role
  6 + add_index :role_assignments, [:resource_id, :resource_type]
  7 + add_index :role_assignments, [:resource_id, :resource_type, :role_id], name: :index_on_role_assigments_resource_role
  8 + add_index :role_assignments, [:accessor_id, :accessor_type, :resource_id, :resource_type], name: :index_on_role_assigments_accessor_resource_role
  9 + add_index :profiles, [:type]
  10 + add_index :profiles, [:visible]
  11 + add_index :profiles, [:enabled]
  12 + add_index :profiles, [:validated]
  13 + end
  14 +
  15 +end
db/migrate/20150223180807_add_private_token_info_to_users.rb 0 → 100644
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
  1 +class AddPrivateTokenInfoToUsers < ActiveRecord::Migration
  2 + def self.up
  3 + add_column :users, :private_token, :string
  4 + add_column :users, :private_token_generated_at, :datetime
  5 + end
  6 +
  7 + def self.down
  8 + remove_column :users, :private_token
  9 + remove_column :users, :private_token_generated_at
  10 + end
  11 +end
db/migrate/20150423203352_fix_tags_case_differences.rb 0 → 100644
@@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
  1 +class FixTagsCaseDifferences < ActiveRecord::Migration
  2 + def up
  3 + tags = ActsAsTaggableOn::Tag.joins('LEFT JOIN tags as b on LOWER(tags.name) = b.name').where('b.id is null')
  4 + tags.find_each do |tag|
  5 + unless ActsAsTaggableOn::Tag.exists?(:name => tag.name.mb_chars.downcase)
  6 + ActsAsTaggableOn::Tag.create(:name => tag.name.mb_chars.downcase)
  7 + end
  8 + end
  9 +
  10 + execute("UPDATE taggings SET tag_id = new.id FROM taggings AS t INNER JOIN tags AS old ON t.tag_id = old.id INNER JOIN tags AS new ON LOWER(old.name) = new.name WHERE old.id != new.id AND taggings.id = t.id")
  11 +
  12 + execute("UPDATE tags SET taggings_count = (SELECT COUNT(*) FROM taggings WHERE taggings.tag_id = tags.id)")
  13 + execute("DELETE FROM tags WHERE taggings_count = 0")
  14 + end
  15 +
  16 + def down
  17 + say 'This migration is irreversible.'
  18 + end
  19 +end
db/migrate/20150529180110_add_date_format_to_environment.rb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +class AddDateFormatToEnvironment < ActiveRecord::Migration
  2 + def up
  3 + add_column :environments, :date_format, :string, :default => 'month_name_with_year'
  4 + end
  5 +
  6 + def down
  7 + remove_column :environments, :date_format
  8 + end
  9 +end
db/migrate/20150603182105_add_label_to_image.rb 0 → 100644
@@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
  1 +class AddLabelToImage < ActiveRecord::Migration
  2 + def up
  3 + add_column :images, :label, :string, :default => ""
  4 + end
  5 + def down
  6 + remove_column :images, :label
  7 + end
  8 +end
@@ -11,7 +11,7 @@ @@ -11,7 +11,7 @@
11 # 11 #
12 # It's strongly recommended to check this file into your version control system. 12 # It's strongly recommended to check this file into your version control system.
13 13
14 -ActiveRecord::Schema.define(:version => 20150525101430) do 14 +ActiveRecord::Schema.define(:version => 20150603182105) do
15 15
16 create_table "abuse_reports", :force => true do |t| 16 create_table "abuse_reports", :force => true do |t|
17 t.integer "reporter_id" 17 t.integer "reporter_id"
@@ -321,17 +321,18 @@ ActiveRecord::Schema.define(:version =&gt; 20150525101430) do @@ -321,17 +321,18 @@ ActiveRecord::Schema.define(:version =&gt; 20150525101430) do
321 t.text "design_data" 321 t.text "design_data"
322 t.text "custom_header" 322 t.text "custom_header"
323 t.text "custom_footer" 323 t.text "custom_footer"
324 - t.string "theme", :default => "default", :null => false 324 + t.string "theme", :default => "default", :null => false
325 t.text "terms_of_use_acceptance_text" 325 t.text "terms_of_use_acceptance_text"
326 t.datetime "created_at" 326 t.datetime "created_at"
327 t.datetime "updated_at" 327 t.datetime "updated_at"
328 - t.integer "reports_lower_bound", :default => 0, :null => false 328 + t.integer "reports_lower_bound", :default => 0, :null => false
329 t.string "redirection_after_login", :default => "keep_on_same_page" 329 t.string "redirection_after_login", :default => "keep_on_same_page"
330 t.text "signup_welcome_text" 330 t.text "signup_welcome_text"
331 t.string "languages" 331 t.string "languages"
332 t.string "default_language" 332 t.string "default_language"
333 t.string "noreply_email" 333 t.string "noreply_email"
334 t.string "redirection_after_signup", :default => "keep_on_same_page" 334 t.string "redirection_after_signup", :default => "keep_on_same_page"
  335 + t.string "date_format", :default => "month_name_with_year"
335 end 336 end
336 337
337 create_table "external_feeds", :force => true do |t| 338 create_table "external_feeds", :force => true do |t|
@@ -376,6 +377,7 @@ ActiveRecord::Schema.define(:version =&gt; 20150525101430) do @@ -376,6 +377,7 @@ ActiveRecord::Schema.define(:version =&gt; 20150525101430) do
376 t.integer "width" 377 t.integer "width"
377 t.integer "height" 378 t.integer "height"
378 t.boolean "thumbnails_processed", :default => false 379 t.boolean "thumbnails_processed", :default => false
  380 + t.string "label", :default => ""
379 end 381 end
380 382
381 add_index "images", ["parent_id"], :name => "index_images_on_parent_id" 383 add_index "images", ["parent_id"], :name => "index_images_on_parent_id"
@@ -692,6 +694,7 @@ ActiveRecord::Schema.define(:version =&gt; 20150525101430) do @@ -692,6 +694,7 @@ ActiveRecord::Schema.define(:version =&gt; 20150525101430) do
692 t.integer "image_id" 694 t.integer "image_id"
693 t.boolean "spam", :default => false 695 t.boolean "spam", :default => false
694 t.integer "responsible_id" 696 t.integer "responsible_id"
  697 + t.integer "closed_by_id"
695 end 698 end
696 699
697 add_index "tasks", ["requestor_id"], :name => "index_tasks_on_requestor_id" 700 add_index "tasks", ["requestor_id"], :name => "index_tasks_on_requestor_id"
debian/changelog
@@ -6,7 +6,10 @@ noosfero (1.2~1) UNRELEASED; urgency=medium @@ -6,7 +6,10 @@ noosfero (1.2~1) UNRELEASED; urgency=medium
6 [ Joenio Costa ] 6 [ Joenio Costa ]
7 * Build noosfero-chat package 7 * Build noosfero-chat package
8 8
9 - -- Joenio Costa <joenio@colivre.coop.br> Mon, 18 May 2015 14:32:21 -0300 9 + [ root ]
  10 + * Api test
  11 +
  12 + -- root <root@17edebf1ae91> Mon, 06 Jul 2015 14:39:06 +0000
10 13
11 noosfero (1.1) wheezy; urgency=low 14 noosfero (1.1) wheezy; urgency=low
12 15
features/approve_article.feature
@@ -62,7 +62,8 @@ Feature: approve article @@ -62,7 +62,8 @@ Feature: approve article
62 And I press "Spread this" 62 And I press "Spread this"
63 And I follow "Delete" 63 And I follow "Delete"
64 And I confirm the browser dialog 64 And I confirm the browser dialog
65 - When I am logged in as "joaosilva" 65 + And I follow "Logout"
  66 + And I am logged in as "joaosilva"
66 And I go to sample-community's control panel 67 And I go to sample-community's control panel
67 And I follow "Process requests" 68 And I follow "Process requests"
68 And I choose "Reject" 69 And I choose "Reject"
features/article_visualization.feature 0 → 100644
@@ -0,0 +1,30 @@ @@ -0,0 +1,30 @@
  1 +Feature: article visualization
  2 + As a user
  3 + I want to change view modes
  4 + In order to see articles in fullscreen or not in fullscreen
  5 +
  6 + Background:
  7 + Given the following users
  8 + | login | name |
  9 + | joaosilva | Joao Silva |
  10 + And "joaosilva" has no articles
  11 + And the following articles
  12 + | owner | name | body |
  13 + | joaosilva | Sample Article | This is an article |
  14 + And I am logged in as "joaosilva"
  15 +
  16 + @selenium
  17 + Scenario: viewing the article in fullscreen by default
  18 + Given I go to /joaosilva/sample-article?fullscreen=1
  19 + Then I should see "Exit full screen"
  20 +
  21 + @selenium
  22 + Scenario: viewing the article not in fullscreen by default
  23 + Given I go to /joaosilva/sample-article
  24 + Then I should see "Full screen"
  25 +
  26 + @selenium
  27 + Scenario: changing the view mode from not in fullscreen to fullscreen
  28 + Given I go to /joaosilva/sample-article
  29 + And I follow "Full screen"
  30 + Then I should see "Exit full screen"
features/balloon.feature
@@ -41,19 +41,19 @@ Feature: balloon @@ -41,19 +41,19 @@ Feature: balloon
41 @selenium 41 @selenium
42 Scenario: I should not see trigger if not enabled on page 42 Scenario: I should not see trigger if not enabled on page
43 Given feature "show_balloon_with_profile_links_when_clicked" is disabled on environment 43 Given feature "show_balloon_with_profile_links_when_clicked" is disabled on environment
44 - When I go to /assets/people 44 + When I go to /search/people
45 Then I should not see "Profile links" 45 Then I should not see "Profile links"
46 46
47 @selenium 47 @selenium
48 Scenario: I should not see trigger by default on page 48 Scenario: I should not see trigger by default on page
49 Given feature "show_balloon_with_profile_links_when_clicked" is enabled on environment 49 Given feature "show_balloon_with_profile_links_when_clicked" is enabled on environment
50 - When I go to /assets/communities 50 + When I go to /search/communities
51 Then I should not see "Members" 51 Then I should not see "Members"
52 52
53 @selenium 53 @selenium
54 Scenario: I should see balloon when clicked on page trigger 54 Scenario: I should see balloon when clicked on page trigger
55 Given feature "show_balloon_with_profile_links_when_clicked" is enabled on environment 55 Given feature "show_balloon_with_profile_links_when_clicked" is enabled on environment
56 - And I go to /assets/communities 56 + And I go to /search/communities
57 And display ".community-trigger" 57 And display ".community-trigger"
58 When I follow "Profile links" 58 When I follow "Profile links"
59 Then I should see "Members" 59 Then I should see "Members"
features/browse_enterprises.feature
@@ -13,20 +13,20 @@ Scenario: show all enterprises @@ -13,20 +13,20 @@ Scenario: show all enterprises
13 Given the following enterprises 13 Given the following enterprises
14 | identifier | name | 14 | identifier | name |
15 | shop2 | Fruits Shop | 15 | shop2 | Fruits Shop |
16 - Given I am on /assets/enterprises 16 + Given I am on /search/enterprises
17 Then I should see "Enterprises" 17 Then I should see "Enterprises"
18 And I should see "Shoes Shop" 18 And I should see "Shoes Shop"
19 And I should see "Fruits Shop" 19 And I should see "Fruits Shop"
20 20
21 Scenario: show profile links button 21 Scenario: show profile links button
22 - Given I am on /assets/enterprises 22 + Given I am on /search/enterprises
23 Then I should see "Profile links" within "a.enterprise-trigger" 23 Then I should see "Profile links" within "a.enterprise-trigger"
24 And I should not see "Members" 24 And I should not see "Members"
25 And I should not see "Agenda" 25 And I should not see "Agenda"
26 26
27 @selenium-fixme 27 @selenium-fixme
28 Scenario: show profile links when clicked 28 Scenario: show profile links when clicked
29 - Given I am on /assets/enterprises 29 + Given I am on /search/enterprises
30 When I follow "Profile links" 30 When I follow "Profile links"
31 Then I should see "Products" within "ul.menu-submenu-list" 31 Then I should see "Products" within "ul.menu-submenu-list"
32 And I should see "Members" within "ul.menu-submenu-list" 32 And I should see "Members" within "ul.menu-submenu-list"
@@ -34,7 +34,7 @@ Scenario: show profile links when clicked @@ -34,7 +34,7 @@ Scenario: show profile links when clicked
34 34
35 @selenium-fixme 35 @selenium-fixme
36 Scenario: go to catalog when click on products link 36 Scenario: go to catalog when click on products link
37 - Given I am on /assets/enterprises 37 + Given I am on /search/enterprises
38 When I follow "Profile links" 38 When I follow "Profile links"
39 And I follow "Products" and wait 39 And I follow "Products" and wait
40 Then I should be exactly on /catalog/shop1 40 Then I should be exactly on /catalog/shop1
features/change_appearance.feature
@@ -14,7 +14,7 @@ Feature: Change appearance @@ -14,7 +14,7 @@ Feature: Change appearance
14 And I should not see an element ".box-4" 14 And I should not see an element ".box-4"
15 And I go to joaosilva's control panel 15 And I go to joaosilva's control panel
16 And I follow "Edit Appearance" 16 And I follow "Edit Appearance"
17 - And I follow "Left Top and Right" 17 + And I follow "Top and Side Bars"
18 And I go to joaosilva's control panel 18 And I go to joaosilva's control panel
19 And I follow "Edit sideboxes" 19 And I follow "Edit sideboxes"
20 And I should see an element ".box-4" 20 And I should see an element ".box-4"
features/events.feature
@@ -17,7 +17,7 @@ Feature: events @@ -17,7 +17,7 @@ Feature: events
17 Then I should see "November 2009" within ".current-month" 17 Then I should see "November 2009" within ".current-month"
18 18
19 Scenario: go to next month in global agenda 19 Scenario: go to next month in global agenda
20 - Given I am on /assets/events?year=2009&month=11 20 + Given I am on /search/events?year=2009&month=11
21 When I follow "December" 21 When I follow "December"
22 Then I should see "December 2009" within ".current-month" 22 Then I should see "December 2009" within ".current-month"
23 23
@@ -27,7 +27,7 @@ Feature: events @@ -27,7 +27,7 @@ Feature: events
27 Then I should see "September 2009" within ".current-month" 27 Then I should see "September 2009" within ".current-month"
28 28
29 Scenario: go to previous month in global agenda 29 Scenario: go to previous month in global agenda
30 - Given I am on /assets/events?year=2009&month=11 30 + Given I am on /search/events?year=2009&month=11
31 When I follow "October" 31 When I follow "October"
32 Then I should see "October 2009" within ".current-month" 32 Then I should see "October 2009" within ".current-month"
33 33
@@ -43,7 +43,7 @@ Feature: events @@ -43,7 +43,7 @@ Feature: events
43 43
44 Scenario: go to specific day in global agenda 44 Scenario: go to specific day in global agenda
45 Given I am on the homepage 45 Given I am on the homepage
46 - When I am on /assets/events?year=2009&month=11&day=12 46 + When I am on /search/events?year=2009&month=11&day=12
47 Then I should see "Events for November, 2009" 47 Then I should see "Events for November, 2009"
48 48
49 Scenario: list events for specific day 49 Scenario: list events for specific day
@@ -88,7 +88,7 @@ Feature: events @@ -88,7 +88,7 @@ Feature: events
88 And the following events 88 And the following events
89 | owner | name | start_date | 89 | owner | name | start_date |
90 | josemanuel | Manuel Birthday | 2009-10-24 | 90 | josemanuel | Manuel Birthday | 2009-10-24 |
91 - When I am on /assets/events?year=2009&month=10&day=24 91 + When I am on /search/events?year=2009&month=10&day=24
92 Then I should see "Another Conference" 92 Then I should see "Another Conference"
93 And I should see "Manuel Birthday" 93 And I should see "Manuel Birthday"
94 94
@@ -157,9 +157,10 @@ Feature: events @@ -157,9 +157,10 @@ Feature: events
157 Then I should not see "New events" link 157 Then I should not see "New events" link
158 158
159 Scenario: display environment name in global agenda 159 Scenario: display environment name in global agenda
160 - When I am on /assets/events 160 + When I am on /search/events
161 Then I should see "Colivre.net's Events" 161 Then I should see "Colivre.net's Events"
162 162
  163 +
163 @selenium 164 @selenium
164 Scenario: published events should be listed in the agenda too 165 Scenario: published events should be listed in the agenda too
165 Given the following community 166 Given the following community
features/profile_domain.feature
@@ -21,9 +21,7 @@ Feature: domain for profile @@ -21,9 +21,7 @@ Feature: domain for profile
21 Scenario: access profile control panel through profile blocks 21 Scenario: access profile control panel through profile blocks
22 Given I am logged in as "joaosilva" 22 Given I am logged in as "joaosilva"
23 When I go to joaosilva's homepage 23 When I go to joaosilva's homepage
24 - And I follow "Control panel" within ".profile-info-block"  
25 - Then I should see "Joao Silva" within "span.control-panel-title"  
26 - When I follow "Control panel" within ".profile-image-block" 24 + And I follow "Control panel" within ".profile-image-block"
27 Then I should see "Joao Silva" within "span.control-panel-title" 25 Then I should see "Joao Silva" within "span.control-panel-title"
28 26
29 @selenium 27 @selenium
features/profile_search.feature
@@ -36,7 +36,7 @@ Feature: search inside a profile @@ -36,7 +36,7 @@ Feature: search inside a profile
36 | joaosilva | ProfileSearchBlock | 36 | joaosilva | ProfileSearchBlock |
37 When I go to joaosilva's profile 37 When I go to joaosilva's profile
38 And I fill in "q" with "bees" within ".profile-search-block" 38 And I fill in "q" with "bees" within ".profile-search-block"
39 - And I press "Search" 39 + And I press "Search" within ".profile-search-block"
40 Then I should see "bees and butterflies" within ".main-block" 40 Then I should see "bees and butterflies" within ".main-block"
41 41
42 Scenario: not display unpublished articles 42 Scenario: not display unpublished articles
features/register_enterprise.feature
@@ -203,5 +203,5 @@ Feature: register enterprise @@ -203,5 +203,5 @@ Feature: register enterprise
203 203
204 Scenario: a user cant see button to register new enterprise if enterprise_registration disabled 204 Scenario: a user cant see button to register new enterprise if enterprise_registration disabled
205 Given feature "enterprise_registration" is disabled on environment 205 Given feature "enterprise_registration" is disabled on environment
206 - When I am on /assets/enterprises 206 + When I am on /search/enterprises
207 Then I should not see "New enterprise" link 207 Then I should not see "New enterprise" link
features/search_enterprises.feature
@@ -56,7 +56,7 @@ Feature: search enterprises @@ -56,7 +56,7 @@ Feature: search enterprises
56 | owner | name | body | homepage | 56 | owner | name | body | homepage |
57 | shop1 | Shoes home | This is the <i>homepage</i> of Shoes shop! It has a very long and pretty vague description, just so we can test wether the system will correctly create an excerpt of this text. We should probably talk about shoes. | true | 57 | shop1 | Shoes home | This is the <i>homepage</i> of Shoes shop! It has a very long and pretty vague description, just so we can test wether the system will correctly create an excerpt of this text. We should probably talk about shoes. | true |
58 When I search enterprises for "shoes" 58 When I search enterprises for "shoes"
59 - And I choose the search filter "Full" 59 + And I select "Full" from "display"
60 Then I should see "This is the homepage of" within ".search-enterprise-description" 60 Then I should see "This is the homepage of" within ".search-enterprise-description"
61 And I should see "about sho..." within ".search-enterprise-description" 61 And I should see "about sho..." within ".search-enterprise-description"
62 62
@@ -66,7 +66,7 @@ Feature: search enterprises @@ -66,7 +66,7 @@ Feature: search enterprises
66 | identifier | name | description | 66 | identifier | name | description |
67 | shop4 | Clothes shop | This <b>clothes</b> shop also sells shoes! This too has a very long and pretty vague description, just so we can test wether the system will correctly create an excerpt of this text. Clothes are a really important part of our lives. | 67 | shop4 | Clothes shop | This <b>clothes</b> shop also sells shoes! This too has a very long and pretty vague description, just so we can test wether the system will correctly create an excerpt of this text. Clothes are a really important part of our lives. |
68 When I search enterprises for "clothes" 68 When I search enterprises for "clothes"
69 - And I choose the search filter "Full" 69 + And I select "Full" from "display"
70 And I should see "This clothes shop" within ".search-enterprise-description" 70 And I should see "This clothes shop" within ".search-enterprise-description"
71 And I should see "really import..." within ".search-enterprise-description" 71 And I should see "really import..." within ".search-enterprise-description"
72 72
features/step_definitions/noosfero_steps.rb
@@ -94,7 +94,7 @@ Given /^the following blocks$/ do |table| @@ -94,7 +94,7 @@ Given /^the following blocks$/ do |table|
94 owner.boxes<< Box.new 94 owner.boxes<< Box.new
95 owner.boxes.first.blocks << MainBlock.new 95 owner.boxes.first.blocks << MainBlock.new
96 end 96 end
97 - box = owner.boxes.where(:position => 3).first 97 + box = owner.boxes.first
98 klass.constantize.create!(item.merge(:box => box)) 98 klass.constantize.create!(item.merge(:box => box))
99 end 99 end
100 end 100 end
features/suggest_article.feature
@@ -14,9 +14,12 @@ Feature: suggest article @@ -14,9 +14,12 @@ Feature: suggest article
14 14
15 @selenium 15 @selenium
16 Scenario: highlight an article before approval of a suggested article 16 Scenario: highlight an article before approval of a suggested article
17 - Given someone suggested the following article to be published  
18 - | target | article_name | article_body | name | email |  
19 - | sample-community | A suggested article | this is an article about whales | jose | jose@example.org | 17 + Given I am on Sample Community's blog
  18 + And I follow "Suggest an article"
  19 + And I fill in "Title" with "Suggestion"
  20 + And I fill in "Your name" with "Some Guy"
  21 + And I fill in "Email" with "someguy@somewhere.com"
  22 + And I press "Save"
20 When I am logged in as "joaosilva" 23 When I am logged in as "joaosilva"
21 And I go to sample-community's control panel 24 And I go to sample-community's control panel
22 And I follow "Process requests" 25 And I follow "Process requests"
lib/noosfero/api/api.rb
1 require 'grape' 1 require 'grape'
2 #require 'rack/contrib' 2 #require 'rack/contrib'
3 -Dir["#{Rails.root}/lib/noosfero/api/*.rb"].each {|file| require_dependency file unless file =~ /api\.rb/} 3 +Dir["#{Rails.root}/lib/noosfero/api/*.rb"].each {|file| require file unless file =~ /api\.rb/}
4 4
5 module Noosfero 5 module Noosfero
6 module API 6 module API
@@ -12,36 +12,29 @@ module Noosfero @@ -12,36 +12,29 @@ module Noosfero
12 use GrapeLogging::Middleware::RequestLogger, { logger: logger } 12 use GrapeLogging::Middleware::RequestLogger, { logger: logger }
13 13
14 rescue_from :all do |e| 14 rescue_from :all do |e|
15 - # Many brave warriors have fallen in the battle for fixing the API log  
16 - # Please, don't remove these 2 lines until the API log problem has  
17 - # been PROPERLY fixed by our savior!!!  
18 - # Otherwise we will have no clue of what went wrong in the API  
19 - puts "API error during processing: #{$!}"  
20 - puts "Backtrace:\n\t#{e.backtrace.join("\n\t")}"  
21 - # Thanks!  
22 logger.error e 15 logger.error e
23 end 16 end
24 17
25 @@NOOSFERO_CONF = nil 18 @@NOOSFERO_CONF = nil
26 -  
27 def self.NOOSFERO_CONF 19 def self.NOOSFERO_CONF
28 - if @@NOOSFERO_CONF 20 + if @@NOOSFERO_CONF
29 @@NOOSFERO_CONF 21 @@NOOSFERO_CONF
30 else 22 else
31 file = Rails.root.join('config', 'noosfero.yml') 23 file = Rails.root.join('config', 'noosfero.yml')
32 @@NOOSFERO_CONF = File.exists?(file) ? YAML.load_file(file)[Rails.env] || {} : {} 24 @@NOOSFERO_CONF = File.exists?(file) ? YAML.load_file(file)[Rails.env] || {} : {}
33 - end 25 + end
34 end 26 end
35 27
36 before { setup_multitenancy } 28 before { setup_multitenancy }
37 before { detect_stuff_by_domain } 29 before { detect_stuff_by_domain }
  30 + before { filter_disabled_plugins_endpoints }
38 after { set_session_cookie } 31 after { set_session_cookie }
39 32
40 version 'v1' 33 version 'v1'
41 prefix "api" 34 prefix "api"
42 format :json 35 format :json
43 content_type :txt, "text/plain" 36 content_type :txt, "text/plain"
44 - 37 +
45 helpers APIHelpers 38 helpers APIHelpers
46 39
47 mount V1::Articles 40 mount V1::Articles
@@ -54,6 +47,7 @@ module Noosfero @@ -54,6 +47,7 @@ module Noosfero
54 mount V1::Tasks 47 mount V1::Tasks
55 mount V1::Tags 48 mount V1::Tags
56 mount V1::Environments 49 mount V1::Environments
  50 +
57 mount Session 51 mount Session
58 52
59 # hook point which allow plugins to add Grape::API extensions to API::API 53 # hook point which allow plugins to add Grape::API extensions to API::API
@@ -66,6 +60,26 @@ module Noosfero @@ -66,6 +60,26 @@ module Noosfero
66 end 60 end
67 end 61 end
68 end 62 end
  63 +
  64 + def self.endpoint_unavailable?(endpoint, environment)
  65 + api_class = endpoint.options[:app] || endpoint.options[:for]
  66 + if api_class.present?
  67 + klass = api_class.name.deconstantize.constantize
  68 + return klass < Noosfero::Plugin && !environment.plugin_enabled?(klass)
  69 + end
  70 + end
  71 +
  72 + class << self
  73 + def endpoints_with_plugins(environment = nil)
  74 + if environment.present?
  75 + cloned_endpoints = endpoints_without_plugins.dup
  76 + cloned_endpoints.delete_if { |endpoint| endpoint_unavailable?(endpoint, environment) }
  77 + else
  78 + endpoints_without_plugins
  79 + end
  80 + end
  81 + alias_method_chain :endpoints, :plugins
  82 + end
69 end 83 end
70 end 84 end
71 -end  
72 \ No newline at end of file 85 \ No newline at end of file
  86 +end
lib/noosfero/api/entities.rb
1 module Noosfero 1 module Noosfero
2 module API 2 module API
3 module Entities 3 module Entities
4 - 4 +
5 Entity.format_with :timestamp do |date| 5 Entity.format_with :timestamp do |date|
6 date.strftime('%Y/%m/%d %H:%M:%S') if date 6 date.strftime('%Y/%m/%d %H:%M:%S') if date
7 end 7 end
8 - 8 +
9 class Image < Entity 9 class Image < Entity
10 root 'images', 'image' 10 root 'images', 'image'
11 11
12 expose :url do |image, options| 12 expose :url do |image, options|
13 image.public_filename 13 image.public_filename
14 end 14 end
15 - 15 +
16 expose :icon_url do |image, options| 16 expose :icon_url do |image, options|
17 image.public_filename(:icon) 17 image.public_filename(:icon)
18 end 18 end
19 - 19 +
20 expose :minor_url do |image, options| 20 expose :minor_url do |image, options|
21 image.public_filename(:minor) 21 image.public_filename(:minor)
22 end 22 end
23 - 23 +
24 expose :portrait_url do |image, options| 24 expose :portrait_url do |image, options|
25 image.public_filename(:portrait) 25 image.public_filename(:portrait)
26 end 26 end
27 - 27 +
28 expose :thumb_url do |image, options| 28 expose :thumb_url do |image, options|
29 image.public_filename(:thumb) 29 image.public_filename(:thumb)
30 end 30 end
31 end 31 end
32 - 32 +
33 class Profile < Entity 33 class Profile < Entity
34 expose :identifier, :name, :id 34 expose :identifier, :name, :id
35 expose :created_at, :format_with => :timestamp 35 expose :created_at, :format_with => :timestamp
36 expose :image, :using => Image 36 expose :image, :using => Image
37 end 37 end
38 - 38 +
  39 + class UserBasic < Entity
  40 + expose :id
  41 + expose :login
  42 + end
  43 +
39 class Person < Profile 44 class Person < Profile
40 root 'people', 'person' 45 root 'people', 'person'
  46 + expose :user, :using => UserBasic
41 end 47 end
  48 +
42 class Enterprise < Profile 49 class Enterprise < Profile
43 root 'enterprises', 'enterprise' 50 root 'enterprises', 'enterprise'
44 end 51 end
  52 +
45 class Community < Profile 53 class Community < Profile
46 root 'communities', 'community' 54 root 'communities', 'community'
47 expose :description 55 expose :description
48 end 56 end
49 -  
50 - class Category < Entity 57 +
  58 + class CategoryBase < Entity
  59 + root 'categories', 'category'
  60 + expose :name, :id
  61 + end
  62 +
  63 + class Category < CategoryBase
51 root 'categories', 'category' 64 root 'categories', 'category'
52 - expose :name, :id, :slug 65 + expose :slug
  66 + expose :full_name do |category, options|
  67 + category.full_name
  68 + end
  69 + expose :parent, :using => CategoryBase, if: { parent: true }
  70 + expose :children, :using => CategoryBase, if: { children: true }
53 expose :image, :using => Image 71 expose :image, :using => Image
54 end 72 end
55 - 73 +
56 class ArticleBase < Entity 74 class ArticleBase < Entity
57 root 'articles', 'article' 75 root 'articles', 'article'
58 expose :id 76 expose :id
@@ -87,8 +105,8 @@ module Noosfero @@ -87,8 +105,8 @@ module Noosfero
87 expose :created_at, :format_with => :timestamp 105 expose :created_at, :format_with => :timestamp
88 expose :author, :using => Profile 106 expose :author, :using => Profile
89 end 107 end
90 -  
91 - 108 +
  109 +
92 class User < Entity 110 class User < Entity
93 root 'users', 'user' 111 root 'users', 'user'
94 expose :id 112 expose :id
@@ -98,13 +116,13 @@ module Noosfero @@ -98,13 +116,13 @@ module Noosfero
98 output = {} 116 output = {}
99 user.person.role_assignments.map do |role_assigment| 117 user.person.role_assignments.map do |role_assigment|
100 if role_assigment.resource.respond_to?(:identifier) 118 if role_assigment.resource.respond_to?(:identifier)
101 - output[role_assigment.resource.identifier] = role_assigment.role.permissions 119 + output[role_assigment.resource.identifier] = role_assigment.role.permissions
102 end 120 end
103 end 121 end
104 output 122 output
105 end 123 end
106 end 124 end
107 - 125 +
108 class UserLogin < User 126 class UserLogin < User
109 expose :private_token 127 expose :private_token
110 end 128 end
@@ -119,6 +137,12 @@ module Noosfero @@ -119,6 +137,12 @@ module Noosfero
119 expose :name 137 expose :name
120 end 138 end
121 139
  140 + class Tag < Entity
  141 + root 'tags', 'tag'
  142 + expose :name
  143 + end
  144 +
  145 +
122 end 146 end
123 end 147 end
124 end 148 end