Commit 8f42e790ed5d0191e62237e24a6e0a68514ff087
1 parent
e22e8356
Exists in
master
and in
29 other branches
merging with stable
Showing
1039 changed files
with
144546 additions
and
114933 deletions
Show diff stats
Too many changes.
To preserve performance only 100 of 1039 files displayed.
AUTHORS
... | ... | @@ -13,16 +13,30 @@ Alessandro Palmeira + Caio Salgado <alessandro.palmeira@gmail.com> |
13 | 13 | Alessandro Palmeira + Caio Salgado <caio.csalgado@gmail.com> |
14 | 14 | Alessandro Palmeira + Caio Salgado + Diego Araújo + João M. M. da Silva <diegoamc90@gmail.com> |
15 | 15 | Alessandro Palmeira + Carlos Morais <alessandro.palmeira@gmail.com> |
16 | +Alessandro Palmeira + Daniel Alves <alessandro.palmeira@gmail.com> | |
17 | +Alessandro Palmeira + Daniel Alves + Diego Araújo <diegoamc90@gmail.com> | |
18 | +Alessandro Palmeira + Daniel Alves + Diego Araújo + Guilherme Rojas <danpaulalves@gmail.com> | |
19 | +Alessandro Palmeira + Diego Araujo <alessandro.palmeira@gmail.com> | |
16 | 20 | Alessandro Palmeira + Diego Araújo <alessandro.palmeira@gmail.com> |
21 | +Alessandro Palmeira + Diego Araujo + Daniela Feitosa <alessandro.palmeira@gmail.com> | |
22 | +Alessandro Palmeira + Diego Araujo <diegoamc90@gmail.com> | |
17 | 23 | Alessandro Palmeira + Diego Araújo <diegoamc90@gmail.com> |
24 | +Alessandro Palmeira + Diego Araujo + Eduardo Morais <alessandro.palmeira@gmail.com> | |
25 | +Alessandro Palmeira + Diego Araújo + João M. M. da Silva <alessandro.palmeira@gmail.com> | |
26 | +Alessandro Palmeira + Diego Araújo + João M. M. da Silva <diegoamc90@gmail.com> | |
27 | +Alessandro Palmeira + Diego Araujo + João M. M. da Silva + Paulo Meirelles <alessandro.palmeira@gmail.com> | |
18 | 28 | Alessandro Palmeira + Diego Araújo + Pedro Leal <diegoamc90@gmail.com> |
19 | 29 | Alessandro Palmeira + Diego Araújo + Pedro Leal + João M. M. da Silva <diegoamc90@gmail.com> |
20 | 30 | Alessandro Palmeira + Diego Araujo + Rafael Manzo <alessandro.palmeira@gmail.com> |
31 | +Alessandro Palmeira + Eduardo Morais <alessandro.palmeira@gmail.com> | |
32 | +Alessandro Palmeira + Guilherme Rojas <alessandro.palmeira@gmail.com> | |
21 | 33 | Alessandro Palmeira + Jefferson Fernandes <alessandro.palmeira@gmail.com> |
22 | 34 | Alessandro Palmeira + João M. M. da Silva <alessandro.palmeira@gmail.com> |
35 | +Alessandro Palmeira + Joao M. M. da Silva + Diego Araujo <alessandro.palmeira@gmail.com> | |
23 | 36 | Alessandro Palmeira + João M. M. da Silva + Renan Teruo <alessandro.palmeira@gmail.com> |
24 | 37 | Alessandro Palmeira + João M. M. Silva <alessandro.palmeira@gmail.com> |
25 | 38 | Alessandro Palmeira + Paulo Meirelles <alessandro.palmeira@gmail.com> |
39 | +Alessandro Palmeira + Paulo Meirelles + João M. M. da Silva <alessandro.palmeira@gmail.com> | |
26 | 40 | Alessandro Palmeira + Rafael Manzo <alessandro.palmeira@gmail.com> |
27 | 41 | Antonio Terceiro + Carlos Morais <terceiro@colivre.coop.br> |
28 | 42 | Antonio Terceiro + Paulo Meirelles <terceiro@colivre.coop.br> |
... | ... | @@ -32,6 +46,7 @@ Braulio Bhavamitra <brauliobo@gmail.com> |
32 | 46 | Bráulio Bhavamitra <brauliobo@gmail.com> |
33 | 47 | Caio <caio.csalgado@gmail.com> |
34 | 48 | Caio + Diego + Pedro + João <caio.csalgado@gmail.com> |
49 | +Caio Formiga <caio.formiga@gmail.com> | |
35 | 50 | Caio, Pedro <caio.csalgado@gmail.com> |
36 | 51 | Caio Salgado + Alessandro Palmeira <caio.csalgado@gmail.com> |
37 | 52 | Caio Salgado <caio.csalgado@gmail.com> |
... | ... | @@ -57,26 +72,42 @@ Carlos Morais + Diego Araújo <diegoamc90@gmail.com> |
57 | 72 | Carlos Morais + Eduardo Morais <carlos88morais@gmail.com> |
58 | 73 | Carlos Morais + Paulo Meirelles <carlos88morais@gmail.com> |
59 | 74 | Carlos Morais + Pedro Leal <carlos88morais@gmail.com> |
75 | +Daniel Alves + Diego Araújo <danpaulalves@gmail.com> | |
76 | +Daniel Alves + Diego Araújo <diegoamc90@gmail.com> | |
77 | +Daniel Alves + Diego Araújo + Guilherme Rojas <danpaulalves@gmail.com> | |
78 | +Daniel Alves + Diego Araújo + Guilherme Rojas <diegoamc90@gmail.com> | |
79 | +Daniel Alves + Diego Araújo + Guilherme Rojas <guilhermehrojas@gmail.com> | |
80 | +Daniel Alves + Guilherme Rojas <danpaulalves@gmail.com> | |
81 | +Daniel Alves + Rafael Manzo <rr.manzo@gmail.com> | |
60 | 82 | Daniela Soares Feitosa <danielafeitosa@colivre.coop.br> |
61 | 83 | Daniel Cunha <daniel@colivre.coop.br> |
62 | 84 | diegoamc <diegoamc90@gmail.com> |
63 | 85 | Diego Araújo + Alessandro Palmeira <diegoamc90@gmail.com> |
86 | +Diego Araújo + Alessandro Palmeira + João M. M. da Silva <diegoamc90@gmail.com> | |
87 | +Diego Araújo + Alessandro Palmeira + Rafael Manzo <rr.manzo@gmail.com> | |
64 | 88 | Diego Araujo + Caio Salgado <diegoamc90@gmail.com> |
89 | +Diego Araújo + Daniel Alves + Rafael Manzo <rr.manzo@gmail.com> | |
65 | 90 | Diego Araújo <diegoamc90@gmail.com> |
91 | +Diego Araújo + Eduardo Morais + Paulo Meirelles <diegoamc90@gmail.com> | |
92 | +Diego Araújo + Guilherme Rojas <diegoamc90@gmail.com> | |
66 | 93 | Diego Araújo + Jefferson Fernandes <diegoamc90@gmail.com> |
67 | 94 | Diego Araujo + Jefferson Fernandes <jeffs.fernandes@gmail.com> |
68 | 95 | Diego Araújo + João Machini <diegoamc90@gmail.com> |
69 | 96 | Diego Araújo + João Machini <digoamc90@gmail.com> |
97 | +Diego Araújo + João M. M. da Silva + Alessandro Palmeira <jaodsilv@linux.ime.usp.br> | |
70 | 98 | Diego Araújo + João M. M. da Silva <diegoamc90@gmail.com> |
71 | 99 | Diego Araújo + João M. M. da Silva + João Machini <diegoamc90@gmail.com> |
72 | 100 | Diego Araújo + João M. M. da Silva + Pedro Leal <diegoamc90@gmail.com> |
73 | 101 | Diego Araújo + Paulo Meirelles <diegoamc90@gmail.com> |
74 | 102 | Diego Araújo + Pedro Leal <diegoamc90@gmail.com> |
103 | +Diego Araujo + Rafael Manzo <diegoamc90@gmail.com> | |
75 | 104 | Diego Araújo + Rafael Manzo <diegoamc90@gmail.com> |
76 | 105 | Diego Araújo + Renan Teruo + Alessandro Palmeira <diegoamc90@gmail.com> |
77 | 106 | Diego Araújo + Renan Teruo <diegoamc90@gmail.com> |
107 | +Diego Araujo + Rodrigo Souto + Rafael Manzo <rr.manzo@gmail.com> | |
78 | 108 | Diego + Jefferson <diegoamc90@gmail.com> |
79 | 109 | Diego Martinez <diegoamc90@gmail.com> |
110 | +Diego Martinez <diego@diego-K55A.(none)> | |
80 | 111 | Diego + Renan <renanteruoc@gmail.com> |
81 | 112 | Fernanda Lopes <nanda.listas+psl@gmail.com> |
82 | 113 | Grazieno Pellegrino <grazieno@gmail.com> |
... | ... | @@ -89,6 +120,7 @@ João da Silva <jaodsilv@linux.ime.usp.br> |
89 | 120 | João Marco Maciel da Silva + Rafael Manzo + Renan Teruo <jaodsilv@linux.ime.usp.br> |
90 | 121 | João M. M. da Silva + Alessandro Palmeira + Diego Araújo + Caio Salgado <jaodsilv@linux.ime.usp.br> |
91 | 122 | João M. M. da Silva + Alessandro Palmeira + Diego Araújo <jaodsilv@linux.ime.usp.br> |
123 | +Joao M. M. da Silva + Alessandro Palmeira <jaodsilv@linux.ime.usp.br> | |
92 | 124 | João M. M. da Silva + Alessandro Palmeira <jaodsilv@linux.ime.usp.br> |
93 | 125 | João M. M. da Silva + Alessandro Palmeira + João Machini <jaodsilv@linux.ime.usp.br> |
94 | 126 | João M. M. da Silva + Caio Salgado + Alessandro Palmeira <jaodsilv@linux.ime.usp.br> |
... | ... | @@ -120,21 +152,30 @@ Larissa Reis <reiss.larissa@gmail.com> |
120 | 152 | Leandro Nunes dos Santos <leandronunes@gmail.com> |
121 | 153 | Leandro Nunes dos Santos <leandro.santos@serpro.gov.br> |
122 | 154 | LinguÁgil 2010 <linguagil.bahia@gmail.com> |
155 | +Lucas Melo <lucas@colivre.coop.br> | |
123 | 156 | Luis David Aguilar Carlos <ludwig9003@gmail.com> |
124 | 157 | Martín Olivera <molivera@solar.org.ar> |
125 | 158 | Moises Machado <moises@colivre.coop.br> |
126 | 159 | Nanda Lopes <nanda.listas+psl@gmail.com> |
160 | +Paulo Meirelles + Alessandro Palmeira + João M. M. da Silva <paulo@softwarelivre.org> | |
127 | 161 | Paulo Meirelles + Alessandro Palmeira <paulo@softwarelivre.org> |
128 | 162 | Paulo Meirelles + Carlos Morais <paulo@softwarelivre.org> |
129 | 163 | Paulo Meirelles + Diego Araújo <paulo@softwarelivre.org> |
130 | 164 | Paulo Meirelles + João M. M. da Silva <paulo@softwarelivre.org> |
131 | 165 | Paulo Meirelles <paulo@softwarelivre.org> |
166 | +Paulo Meirelles + Rafael Manzo <paulo@softwarelivre.org> | |
132 | 167 | Rafael Gomes <rafaelgomes@techfree.com.br> |
168 | +Rafael Manzo + Alessandro Palmeira <rr.manzo@gmail.com> | |
169 | +Rafael Manzo + Daniel Alves <danpaulalves@gmail.com> | |
170 | +Rafael Manzo + Diego Araújo <rr.manzo@gmail.com> | |
133 | 171 | Rafael Manzo + João M. M. Silva <rr.manzo@gmail.com> |
172 | +Rafael Manzo + Paulo Meirelles <rr.manzo@gmail.com> | |
134 | 173 | Rafael Martins <rmmartins@gmail.com> |
135 | 174 | Rafael Reggiani Manzo + Caio Salgado + Jefferson Fernandes <rr.manzo@gmail.com> |
136 | 175 | Rafael Reggiani Manzo + Diego Araujo <diegoamc90@gmail.com> |
137 | 176 | Rafael Reggiani Manzo + Diego Araujo <rr.manzo@gmail.com> |
177 | +Rafael Reggiani Manzo + Diego Araújo <rr.manzo@gmail.com> | |
178 | +Rafael Reggiani Manzo + João M. M. da Silva <rr.manzo@gmail.com> | |
138 | 179 | Rafael Reggiani Manzo <rr.manzo@gmail.com> |
139 | 180 | Raphaël Rousseau <raph@r4f.org> |
140 | 181 | Raquel Lira <raquel.lira@gmail.com> |
... | ... | @@ -146,8 +187,11 @@ Renan Teruo + Paulo Meirelles <renanteruoc@gmail.com> |
146 | 187 | Renan Teruo + Rafael Manzo <renanteruoc@gmail.com> |
147 | 188 | Rodrigo Souto <rodrigo@colivre.coop.br> |
148 | 189 | Ronny Kursawe <kursawe.ronny@googlemail.com> |
190 | +root <root@debian.sdr.serpro> | |
149 | 191 | Samuel R. C. Vale <srcvale@holoscopio.com> |
150 | 192 | Valessio Brito <valessio@gmail.com> |
193 | +vfcosta <vfcosta@gmail.com> | |
194 | +Visita <visita@debian.(none)> | |
151 | 195 | Yann Lugrin <yann.lugrin@liquid-concept.ch> |
152 | 196 | |
153 | 197 | Ideas, specifications and incentive | ... | ... |
Gemfile
1 | -source :rubygems | |
2 | -gem 'cucumber', '0.4.0' | |
3 | -gem 'webrat', '0.5.1' | |
4 | -gem 'rspec', '1.2.9' | |
5 | -gem 'rspec-rails', '1.2.9' | |
6 | -gem 'Selenium', '>= 1.1.14' | |
7 | -gem 'selenium-client', '>= 1.2.17' | |
8 | -gem 'database_cleaner' | |
1 | +source "https://rubygems.org" | |
2 | + | |
9 | 3 | gem 'exception_notification', '1.0.20090728' |
10 | 4 | gem 'system_timer' |
11 | 5 | |
6 | +group :test do | |
7 | + gem 'rspec', '1.2.9' | |
8 | + gem 'rspec-rails', '1.2.9' | |
9 | +end | |
10 | + | |
11 | +group :cucumber do | |
12 | + gem 'rake', '0.8.7' | |
13 | + gem 'cucumber-rails', '0.3.2' | |
14 | + gem 'capybara', '1.1.1' | |
15 | + gem 'cucumber', '1.1.0' | |
16 | + gem 'database_cleaner' | |
17 | +end | |
18 | + | |
12 | 19 | def program(name) |
13 | 20 | unless system("which #{name} > /dev/null") |
14 | 21 | puts "W: Program #{name} is needed, but was not found in your PATH" | ... | ... |
Gemfile.lock
1 | 1 | GEM |
2 | - remote: http://rubygems.org/ | |
2 | + remote: https://rubygems.org/ | |
3 | 3 | specs: |
4 | - Selenium (1.1.14) | |
5 | - builder (3.0.0) | |
6 | - cucumber (0.4.0) | |
4 | + builder (3.1.4) | |
5 | + capybara (1.1.1) | |
6 | + mime-types (>= 1.16) | |
7 | + nokogiri (>= 1.3.3) | |
8 | + rack (>= 1.0.0) | |
9 | + rack-test (>= 0.5.4) | |
10 | + selenium-webdriver (~> 2.0) | |
11 | + xpath (~> 0.1.4) | |
12 | + childprocess (0.3.6) | |
13 | + ffi (~> 1.0, >= 1.0.6) | |
14 | + cucumber (1.1.0) | |
7 | 15 | builder (>= 2.1.2) |
8 | 16 | diff-lcs (>= 1.1.2) |
9 | - polyglot (>= 0.2.9) | |
10 | - term-ansicolor (>= 1.0.3) | |
11 | - treetop (>= 1.4.2) | |
12 | - database_cleaner (0.7.0) | |
17 | + gherkin (~> 2.5.0) | |
18 | + json (>= 1.4.6) | |
19 | + term-ansicolor (>= 1.0.6) | |
20 | + cucumber-rails (0.3.2) | |
21 | + cucumber (>= 0.8.0) | |
22 | + database_cleaner (0.9.1) | |
13 | 23 | diff-lcs (1.1.3) |
14 | 24 | exception_notification (1.0.20090728) |
15 | - nokogiri (1.5.0) | |
16 | - polyglot (0.3.3) | |
17 | - rack (1.3.5) | |
25 | + ffi (1.2.0) | |
26 | + gherkin (2.5.4) | |
27 | + json (>= 1.4.6) | |
28 | + json (1.7.5) | |
29 | + libwebsocket (0.1.6.1) | |
30 | + websocket | |
31 | + mime-types (1.19) | |
32 | + multi_json (1.3.7) | |
33 | + nokogiri (1.5.5) | |
34 | + rack (1.1.0) | |
35 | + rack-test (0.6.2) | |
36 | + rack (>= 1.0) | |
37 | + rake (0.8.7) | |
18 | 38 | rspec (1.2.9) |
19 | 39 | rspec-rails (1.2.9) |
20 | 40 | rack (>= 1.0.0) |
21 | 41 | rspec (>= 1.2.9) |
22 | - selenium-client (1.2.18) | |
42 | + rubyzip (0.9.9) | |
43 | + selenium-webdriver (2.26.0) | |
44 | + childprocess (>= 0.2.5) | |
45 | + libwebsocket (~> 0.1.3) | |
46 | + multi_json (~> 1.0) | |
47 | + rubyzip | |
23 | 48 | system_timer (1.2.4) |
24 | 49 | term-ansicolor (1.0.7) |
25 | - treetop (1.4.10) | |
26 | - polyglot | |
27 | - polyglot (>= 0.3.1) | |
28 | - webrat (0.5.1) | |
29 | - nokogiri (>= 1.2.0) | |
30 | - rack (>= 1.0) | |
50 | + websocket (1.0.4) | |
51 | + xpath (0.1.4) | |
52 | + nokogiri (~> 1.3) | |
31 | 53 | |
32 | 54 | PLATFORMS |
33 | 55 | ruby |
34 | 56 | |
35 | 57 | DEPENDENCIES |
36 | - Selenium (>= 1.1.14) | |
37 | - cucumber (= 0.4.0) | |
58 | + capybara (= 1.1.1) | |
59 | + cucumber (= 1.1.0) | |
60 | + cucumber-rails (= 0.3.2) | |
38 | 61 | database_cleaner |
39 | 62 | exception_notification (= 1.0.20090728) |
63 | + rake (= 0.8.7) | |
40 | 64 | rspec (= 1.2.9) |
41 | 65 | rspec-rails (= 1.2.9) |
42 | - selenium-client (>= 1.2.17) | |
43 | 66 | system_timer |
44 | - webrat (= 0.5.1) | ... | ... |
INSTALL
... | ... | @@ -33,7 +33,7 @@ You need to install some packages Noosfero depends on. On Debian GNU/Linux or |
33 | 33 | Debian-based systems, all of these packages are available through the Debian |
34 | 34 | archive. You can install them with the following command: |
35 | 35 | |
36 | - # apt-get install ruby rake po4a libgettext-ruby-util libgettext-ruby1.8 libsqlite3-ruby rcov librmagick-ruby libredcloth-ruby libwill-paginate-ruby iso-codes libfeedparser-ruby openjdk-6-jre libdaemons-ruby thin tango-icon-theme libhpricot-ruby | |
36 | + # apt-get install ruby rake po4a libgettext-ruby-util libgettext-ruby1.8 libsqlite3-ruby rcov librmagick-ruby libredcloth-ruby libwill-paginate-ruby iso-codes libfeedparser-ruby libdaemons-ruby thin tango-icon-theme libhpricot-ruby | |
37 | 37 | |
38 | 38 | On other systems, they may or may not be available through your regular package |
39 | 39 | management system. Below are the links to their homepages. |
... | ... | @@ -43,7 +43,6 @@ management system. Below are the links to their homepages. |
43 | 43 | * po4a: http://po4a.alioth.debian.org/ |
44 | 44 | * Ruby-sqlite3: http://rubyforge.org/projects/sqlite-ruby |
45 | 45 | * rcov: http://eigenclass.org/hiki/rcov |
46 | -* Solr: http://lucene.apache.org/solr | |
47 | 46 | * RMagick: http://rmagick.rubyforge.org/ |
48 | 47 | * RedCloth: http://redcloth.org/ |
49 | 48 | * will_paginate: http://github.com/mislav/will_paginate/wikis |
... | ... | @@ -111,9 +110,6 @@ $ tar -zxvf noosfero-0.39.0.tar.gz |
111 | 110 | $ ln -s noosfero-0.39.0 current |
112 | 111 | $ cd current |
113 | 112 | |
114 | -Copy config/solr.yml.dist to config/solr.yml. You will | |
115 | -probably not need to customize this configuration, but have a look at it. | |
116 | - | |
117 | 113 | Create the thin configuration file: |
118 | 114 | |
119 | 115 | $ thin -C config/thin.yml -e production config |
... | ... | @@ -195,10 +191,6 @@ Compile the translations: |
195 | 191 | |
196 | 192 | $ RAILS_ENV=production rake noosfero:translations:compile |
197 | 193 | |
198 | -Run Solr: | |
199 | - | |
200 | -$ rake solr:start | |
201 | - | |
202 | 194 | Now we must create some initial data. To create your default environment |
203 | 195 | (the first one), run the command below: |
204 | 196 | ... | ... |
INSTALL.chat
... | ... | @@ -6,15 +6,13 @@ To configure XMPP/BOSH in Noosfero you need: |
6 | 6 | * SystemTimer - http://ph7spot.com/musings/system-timer |
7 | 7 | * Pidgin data files - http://www.pidgin.im/ |
8 | 8 | |
9 | -If you use Debian Lenny: | |
9 | +If you use Debian Wheezy: | |
10 | 10 | |
11 | -# apt-get install librestclient-ruby (from backports) | |
12 | -# apt-get install pidgin-data | |
13 | -# apt-get install ruby1.8-dev | |
11 | +# apt-get install librestclient-ruby pidgin-data ruby1.8-dev | |
14 | 12 | # gem install SystemTimer |
15 | 13 | |
16 | -Take a look at util/chat directory to see samples of config file to configure a | |
17 | -XMPP/BOSH server with ejabberd, postgresql and apache2. | |
14 | +The samples of config file to configure a XMPP/BOSH server with | |
15 | +ejabberd, postgresql and apache2 can be found at util/chat directory. | |
18 | 16 | |
19 | 17 | == XMPP/Chat Server Setup |
20 | 18 | |
... | ... | @@ -22,8 +20,7 @@ This is a step-by-step guide to get a XMPP service working, in a Debian system. |
22 | 20 | |
23 | 21 | 1. Install the required packages |
24 | 22 | |
25 | -# apt-get -t lenny-backports install ejabberd | |
26 | -# apt-get install odbc-postgresql | |
23 | +# apt-get install ejabberd odbc-postgresql | |
27 | 24 | |
28 | 25 | 2. Ejabberd configuration |
29 | 26 | |
... | ... | @@ -108,7 +105,7 @@ Unused modules can be disabled, for example: |
108 | 105 | * web_admin |
109 | 106 | * mod_pubsub |
110 | 107 | * mod_irc |
111 | - * mod_offine | |
108 | + * mod_offline | |
112 | 109 | * mod_admin_extra |
113 | 110 | * mod_register |
114 | 111 | |
... | ... | @@ -132,7 +129,7 @@ This will create a new schema inside the noosfero database, called 'ejabberd'. |
132 | 129 | |
133 | 130 | Note 'noosfero' user should have permission to create Postgresql schemas. Also, |
134 | 131 | there should be at least one domain with 'is_default = true' in 'domains' |
135 | -table, otherwise people couldn't see your friends online. | |
132 | +table, otherwise people won't be able to see their friends online. | |
136 | 133 | |
137 | 134 | |
138 | 135 | 4. ODBC configuration |
... | ... | @@ -168,9 +165,12 @@ Debug = 0 |
168 | 165 | CommLog = 1 |
169 | 166 | UsageCount = 3 |
170 | 167 | |
171 | - * testing all: | |
168 | + 4.1 testing all: | |
172 | 169 | |
173 | -# isql 'PostgreSQLEjabberdNoosfero' DBUSER | |
170 | +# isql 'PostgreSQLEjabberdNoosfero' | |
171 | + | |
172 | +If the configuration was done right, the message "Connected!" | |
173 | +will be displayed. | |
174 | 174 | |
175 | 175 | |
176 | 176 | 5. Enabling kernel polling and SMP in /etc/default/ejabberd | ... | ... |
RELEASING
... | ... | @@ -19,11 +19,12 @@ To prepare a release of noosfero, you must follow the steps below: |
19 | 19 | |
20 | 20 | * Finish all requirements and bugs assigned to the to-be-released version |
21 | 21 | * Make sure all tests pass |
22 | -* Change the version in lib/noosfero.rb and debian/changelog to the | |
23 | - to-be-released version (e.g. 0.2.0, 0.3.1) | |
24 | 22 | * Write release notes at the version's wiki topic |
25 | -* Generate packages with <tt>rake noosfero:release</tt>. Your tarball and deb | |
26 | - pkg will be under the pkg/ directory. This task will create a git tag too. | |
23 | +* Generate packages with <tt>rake noosfero:release[(stable|test)]</tt>. This task will: | |
24 | + * Update the version in lib/noosfero.rb and debian/changelog. | |
25 | + * Create the tarbal and the deb pkg under pkg/ directory. | |
26 | + * Create a git tag and push it. | |
27 | + * Upload the pkg to the configured repository (if configured) on ~/.dput.cf. | |
27 | 28 | * Test that the tarball and deb package are ok |
28 | 29 | * Go to the version's wiki topic and edit it to reflect the new reality |
29 | 30 | * Edit the topic WebPreferences and update DEBIAN_REPOSITORY_TOPICS setting | ... | ... |
Rakefile
... | ... | @@ -7,6 +7,10 @@ require 'rake' |
7 | 7 | require 'rake/testtask' |
8 | 8 | require 'rake/rdoctask' |
9 | 9 | |
10 | -ACTS_AS_SEARCHABLE_ENABLED = false if Rake.application.top_level_tasks.detect{|t| t == 'db:data:minimal'} | |
11 | - | |
10 | +# rails tasks | |
12 | 11 | require 'tasks/rails' |
12 | + | |
13 | +# plugins' tasks | |
14 | +plugins_tasks = Dir.glob("config/plugins/*/{tasks,lib/tasks,rails/tasks}/**/*.rake").sort + | |
15 | + Dir.glob("config/plugins/*/vendor/plugins/*/{tasks,lib/tasks,rails/tasks}/**/*.rake").sort | |
16 | +plugins_tasks.each{ |ext| load ext } | ... | ... |
app/controllers/admin/environment_design_controller.rb
... | ... | @@ -3,7 +3,8 @@ class EnvironmentDesignController < BoxOrganizerController |
3 | 3 | protect 'edit_environment_design', :environment |
4 | 4 | |
5 | 5 | def available_blocks |
6 | - @available_blocks ||= [ ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, PeopleBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock, FeaturedProductsBlock, CategoriesBlock, RawHTMLBlock ] | |
6 | + @available_blocks ||= [ ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, PeopleBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock, FeaturedProductsBlock, CategoriesBlock, RawHTMLBlock, TagsBlock ] | |
7 | + @available_blocks += plugins.dispatch(:extra_blocks, :type => Environment) | |
7 | 8 | end |
8 | 9 | |
9 | 10 | end | ... | ... |
app/controllers/admin/region_validators_controller.rb
... | ... | @@ -33,7 +33,7 @@ class RegionValidatorsController < AdminController |
33 | 33 | def load_region_and_search |
34 | 34 | @region = environment.regions.find(params[:id]) |
35 | 35 | if params[:search] |
36 | - @search = @region.search_possible_validators(params[:search]) | |
36 | + @search = find_by_contents(:organizations, Organization, params[:search])[:results].reject {|item| @region.validator_ids.include?(item.id) } | |
37 | 37 | end |
38 | 38 | end |
39 | 39 | ... | ... |
app/controllers/admin/users_controller.rb
1 | +require 'csv' | |
2 | + | |
1 | 3 | class UsersController < AdminController |
2 | 4 | |
3 | 5 | protect 'manage_environment_users', :environment |
... | ... | @@ -15,8 +17,16 @@ class UsersController < AdminController |
15 | 17 | :disposition => "attachment; filename=users.xml" |
16 | 18 | end |
17 | 19 | format.csv do |
18 | - @users = User.find(:all, :conditions => {:environment_id => environment.id}, :include => [:person]) | |
19 | - render :template => "users/index_csv.rhtml", :content_type => 'text/csv', :layout => false | |
20 | + # using a direct connection with the dbms to optimize | |
21 | + command = User.send(:sanitize_sql, ["SELECT profiles.name, users.email FROM profiles | |
22 | + INNER JOIN users ON profiles.user_id=users.id | |
23 | + WHERE profiles.environment_id = ?", environment.id]) | |
24 | + users = User.connection.execute(command) | |
25 | + csv_content = "name;email\n" | |
26 | + users.each { |u| | |
27 | + CSV.generate_row([u['name'], u['email']], 2, csv_content, fs=';') | |
28 | + } | |
29 | + render :text => csv_content, :content_type => 'text/csv', :layout => false | |
20 | 30 | end |
21 | 31 | end |
22 | 32 | end | ... | ... |
app/controllers/application_controller.rb
... | ... | @@ -154,4 +154,18 @@ class ApplicationController < ActionController::Base |
154 | 154 | end |
155 | 155 | end |
156 | 156 | |
157 | + def find_by_contents(asset, scope, query, paginate_options={:page => 1}, options={}) | |
158 | + scope = scope.send(options[:filter]) if options[:filter] | |
159 | + | |
160 | + @plugins.first(:find_by_contents, asset, scope, query, paginate_options, options) || | |
161 | + fallback_find_by_contents(asset, scope, query, paginate_options, options) | |
162 | + end | |
163 | + | |
164 | + private | |
165 | + | |
166 | + def fallback_find_by_contents(asset, scope, query, paginate_options, options) | |
167 | + return {:results => scope.paginate(paginate_options)} if query.blank? | |
168 | + {:results => scope.like_search(query).paginate(paginate_options)} | |
169 | + end | |
170 | + | |
157 | 171 | end | ... | ... |
app/controllers/box_organizer_controller.rb
... | ... | @@ -68,8 +68,8 @@ class BoxOrganizerController < ApplicationController |
68 | 68 | raise ArgumentError.new("Type %s is not allowed. Go away." % type) |
69 | 69 | end |
70 | 70 | else |
71 | - @center_block_types = Box.acceptable_center_blocks & available_blocks | |
72 | - @side_block_types = Box.acceptable_side_blocks & available_blocks | |
71 | + @center_block_types = (Box.acceptable_center_blocks & available_blocks) + plugins.dispatch(:extra_blocks, :type => boxes_holder.class, :position => 1) | |
72 | + @side_block_types = (Box.acceptable_side_blocks & available_blocks) + plugins.dispatch(:extra_blocks, :type => boxes_holder.class, :position => [2,3]) | |
73 | 73 | @boxes = boxes_holder.boxes |
74 | 74 | render :action => 'add_block', :layout => false |
75 | 75 | end | ... | ... |
app/controllers/my_profile/cms_controller.rb
... | ... | @@ -270,7 +270,7 @@ class CmsController < MyProfileController |
270 | 270 | |
271 | 271 | def search |
272 | 272 | query = params[:q] |
273 | - results = profile.files.published.find_by_contents(query)[:results] | |
273 | + results = find_by_contents(:uploaded_files, profile.files.published, query)[:results] | |
274 | 274 | render :text => article_list_to_json(results), :content_type => 'application/json' |
275 | 275 | end |
276 | 276 | ... | ... |
app/controllers/my_profile/profile_design_controller.rb
... | ... | @@ -7,17 +7,25 @@ class ProfileDesignController < BoxOrganizerController |
7 | 7 | def available_blocks |
8 | 8 | blocks = [ ArticleBlock, TagsBlock, RecentDocumentsBlock, ProfileInfoBlock, LinkListBlock, MyNetworkBlock, FeedReaderBlock, ProfileImageBlock, LocationBlock, SlideshowBlock, ProfileSearchBlock, HighlightsBlock ] |
9 | 9 | |
10 | + blocks += plugins.dispatch(:extra_blocks) | |
11 | + | |
10 | 12 | # blocks exclusive for organizations |
11 | 13 | if profile.has_members? |
12 | 14 | blocks << MembersBlock |
13 | 15 | end |
14 | 16 | |
15 | - # blocks exclusive to person | |
17 | + # blocks exclusive to people | |
16 | 18 | if profile.person? |
17 | 19 | blocks << FriendsBlock |
18 | 20 | blocks << FavoriteEnterprisesBlock |
19 | 21 | blocks << CommunitiesBlock |
20 | 22 | blocks << EnterprisesBlock |
23 | + blocks += plugins.dispatch(:extra_blocks, :type => Person) | |
24 | + end | |
25 | + | |
26 | + # blocks exclusive to communities | |
27 | + if profile.community? | |
28 | + blocks += plugins.dispatch(:extra_blocks, :type => Community) | |
21 | 29 | end |
22 | 30 | |
23 | 31 | # blocks exclusive for enterprises |
... | ... | @@ -26,6 +34,7 @@ class ProfileDesignController < BoxOrganizerController |
26 | 34 | blocks << HighlightsBlock |
27 | 35 | blocks << FeaturedProductsBlock |
28 | 36 | blocks << FansBlock |
37 | + blocks += plugins.dispatch(:extra_blocks, :type => Enterprise) | |
29 | 38 | end |
30 | 39 | |
31 | 40 | # product block exclusive for enterprises in environments that permits it |
... | ... | @@ -33,7 +42,7 @@ class ProfileDesignController < BoxOrganizerController |
33 | 42 | blocks << ProductsBlock |
34 | 43 | end |
35 | 44 | |
36 | - # block exclusive to profile has blog | |
45 | + # block exclusive to profiles that have blog | |
37 | 46 | if profile.has_blog? |
38 | 47 | blocks << BlogArchivesBlock |
39 | 48 | end | ... | ... |
app/controllers/my_profile/profile_members_controller.rb
app/controllers/public/account_controller.rb
... | ... | @@ -71,10 +71,6 @@ class AccountController < ApplicationController |
71 | 71 | @block_bot = !!session[:may_be_a_bot] |
72 | 72 | @invitation_code = params[:invitation_code] |
73 | 73 | begin |
74 | - if params[:user] | |
75 | - params[:user].delete(:password_confirmation_clear) | |
76 | - params[:user].delete(:password_clear) | |
77 | - end | |
78 | 74 | @user = User.new(params[:user]) |
79 | 75 | @user.terms_of_use = environment.terms_of_use |
80 | 76 | @user.environment = environment | ... | ... |
app/controllers/public/catalog_controller.rb
... | ... | @@ -7,7 +7,7 @@ class CatalogController < PublicController |
7 | 7 | def index |
8 | 8 | @category = params[:level] ? ProductCategory.find(params[:level]) : nil |
9 | 9 | @products = @profile.products.from_category(@category).paginate(:order => 'available desc, highlighted desc, name asc', :per_page => 9, :page => params[:page]) |
10 | - @categories = ProductCategory.on_level(params[:level]) | |
10 | + @categories = ProductCategory.on_level(params[:level]).order(:name) | |
11 | 11 | end |
12 | 12 | |
13 | 13 | protected | ... | ... |
app/controllers/public/profile_search_controller.rb
... | ... | @@ -11,7 +11,7 @@ class ProfileSearchController < PublicController |
11 | 11 | if params[:where] == 'environment' |
12 | 12 | redirect_to :controller => 'search', :query => @q |
13 | 13 | else |
14 | - @results = profile.articles.published.find_by_contents(@q, {:per_page => 10, :page => params[:page]})[:results] | |
14 | + @results = find_by_contents(:articles, profile.articles.published, @q, {:per_page => 10, :page => params[:page]})[:results] | |
15 | 15 | end |
16 | 16 | end |
17 | 17 | end | ... | ... |
app/controllers/public/search_controller.rb
... | ... | @@ -4,10 +4,11 @@ class SearchController < PublicController |
4 | 4 | include SearchHelper |
5 | 5 | include ActionView::Helpers::NumberHelper |
6 | 6 | |
7 | - before_filter :redirect_asset_param, :except => [:facets_browse, :assets] | |
7 | + before_filter :redirect_asset_param, :except => :assets | |
8 | 8 | before_filter :load_category |
9 | 9 | before_filter :load_search_assets |
10 | 10 | before_filter :load_query |
11 | + before_filter :load_filter | |
11 | 12 | |
12 | 13 | # Backwards compatibility with old URLs |
13 | 14 | def redirect_asset_param |
... | ... | @@ -17,25 +18,51 @@ class SearchController < PublicController |
17 | 18 | |
18 | 19 | no_design_blocks |
19 | 20 | |
20 | - def facets_browse | |
21 | - @asset = params[:asset] | |
22 | - @asset_class = asset_class(@asset) | |
21 | + def index | |
22 | + @searches = {} | |
23 | + @order = [] | |
24 | + @names = {} | |
25 | + @results_only = true | |
23 | 26 | |
24 | - @facets_only = true | |
25 | - send(@asset) | |
27 | + @enabled_searches.select { |key,description| @searching[key] }.each do |key, description| | |
28 | + load_query | |
29 | + @asset = key | |
30 | + send(key) | |
31 | + @order << key | |
32 | + @names[key] = getterm(description) | |
33 | + end | |
34 | + @asset = nil | |
26 | 35 | |
27 | - @facet = @asset_class.map_facets_for(environment).find { |facet| facet[:id] == params[:facet_id] } | |
28 | - raise 'Facet not found' if @facet.nil? | |
36 | + if @searches.keys.size == 1 | |
37 | + @asset = @searches.keys.first | |
38 | + render :action => @asset | |
39 | + end | |
40 | + end | |
29 | 41 | |
30 | - render :layout => false | |
42 | + # view the summary of one category | |
43 | + def category_index | |
44 | + @searches = {} | |
45 | + @order = [] | |
46 | + @names = {} | |
47 | + limit = MULTIPLE_SEARCH_LIMIT | |
48 | + [ | |
49 | + [ :people, _('People'), :recent_people ], | |
50 | + [ :enterprises, _('Enterprises'), :recent_enterprises ], | |
51 | + [ :products, _('Products'), :recent_products ], | |
52 | + [ :events, _('Upcoming events'), :upcoming_events ], | |
53 | + [ :communities, _('Communities'), :recent_communities ], | |
54 | + [ :articles, _('Contents'), :recent_articles ] | |
55 | + ].each do |asset, name, filter| | |
56 | + @order << asset | |
57 | + @searches[asset]= {:results => @category.send(filter, limit)} | |
58 | + raise "No total_entries for: #{asset}" unless @searches[asset][:results].respond_to?(:total_entries) | |
59 | + @names[asset] = name | |
60 | + end | |
31 | 61 | end |
32 | 62 | |
33 | 63 | def articles |
34 | - if !@empty_query | |
35 | - full_text_search ['public:true'] | |
36 | - else | |
37 | - @results[@asset] = @environment.articles.public.send(@filter).paginate(paginate_options) | |
38 | - end | |
64 | + @scope = @environment.articles.public | |
65 | + full_text_search | |
39 | 66 | end |
40 | 67 | |
41 | 68 | def contents |
... | ... | @@ -43,49 +70,23 @@ class SearchController < PublicController |
43 | 70 | end |
44 | 71 | |
45 | 72 | def people |
46 | - if !@empty_query | |
47 | - full_text_search ['public:true'] | |
48 | - else | |
49 | - @results[@asset] = visible_profiles(Person).send(@filter).paginate(paginate_options) | |
50 | - end | |
73 | + @scope = visible_profiles(Person) | |
74 | + full_text_search | |
51 | 75 | end |
52 | 76 | |
53 | 77 | def products |
54 | - public_filters = ['public:true', 'enabled:true'] | |
55 | - if !@empty_query | |
56 | - full_text_search public_filters | |
57 | - else | |
58 | - @one_page = true | |
59 | - @geosearch = logged_in? && current_user.person.lat && current_user.person.lng | |
60 | - | |
61 | - extra_limit = LIST_SEARCH_LIMIT*5 | |
62 | - sql_options = {:limit => LIST_SEARCH_LIMIT, :order => 'random()'} | |
63 | - if @geosearch | |
64 | - full_text_search public_filters, :sql_options => sql_options, :extra_limit => extra_limit, | |
65 | - :alternate_query => "{!boost b=recip(geodist(),#{"%e" % (1.to_f/DistBoost)},1,1)}", | |
66 | - :radius => DistFilt, :latitude => current_user.person.lat, :longitude => current_user.person.lng | |
67 | - else | |
68 | - full_text_search public_filters, :sql_options => sql_options, :extra_limit => extra_limit, | |
69 | - :boost_functions => ['recip(ms(NOW/HOUR,updated_at),1.3e-10,1,1)'] | |
70 | - end | |
71 | - end | |
78 | + @scope = @environment.products | |
79 | + full_text_search | |
72 | 80 | end |
73 | 81 | |
74 | 82 | def enterprises |
75 | - if !@empty_query | |
76 | - full_text_search ['public:true'] | |
77 | - else | |
78 | - @filter_title = _('Enterprises from network') | |
79 | - @results[@asset] = visible_profiles(Enterprise, [{:products => :product_category}]).paginate(paginate_options) | |
80 | - end | |
83 | + @scope = visible_profiles(Enterprise, [{:products => :product_category}]) | |
84 | + full_text_search | |
81 | 85 | end |
82 | 86 | |
83 | 87 | def communities |
84 | - if !@empty_query | |
85 | - full_text_search ['public:true'] | |
86 | - else | |
87 | - @results[@asset] = visible_profiles(Community).send(@filter).paginate(paginate_options) | |
88 | - end | |
88 | + @scope = visible_profiles(Community) | |
89 | + full_text_search | |
89 | 90 | end |
90 | 91 | |
91 | 92 | def events |
... | ... | @@ -93,7 +94,7 @@ class SearchController < PublicController |
93 | 94 | month = (params[:month] ? params[:month].to_i : Date.today.month) |
94 | 95 | day = (params[:day] ? params[:day].to_i : Date.today.day) |
95 | 96 | date = build_date(params[:year], params[:month], params[:day]) |
96 | - date_range = (date - 1.month)..(date + 1.month).at_end_of_month | |
97 | + date_range = (date - 1.month).at_beginning_of_month..(date + 1.month).at_end_of_month | |
97 | 98 | |
98 | 99 | @selected_day = nil |
99 | 100 | @events_of_the_day = [] |
... | ... | @@ -104,64 +105,21 @@ class SearchController < PublicController |
104 | 105 | environment.events.by_day(@selected_day) |
105 | 106 | end |
106 | 107 | |
107 | - if !@empty_query | |
108 | - full_text_search | |
109 | - else | |
110 | - @results[@asset] = date_range ? environment.events.by_range(date_range) : environment.events | |
111 | - end | |
108 | + @scope = date_range && params[:action] == 'events' ? environment.events.by_range(date_range) : environment.events | |
109 | + full_text_search | |
112 | 110 | |
113 | - events = @results[@asset] | |
111 | + events = @searches[@asset][:results] | |
114 | 112 | @calendar = populate_calendar(date, events) |
115 | 113 | @previous_calendar = populate_calendar(date - 1.month, events) |
116 | 114 | @next_calendar = populate_calendar(date + 1.month, events) |
117 | 115 | end |
118 | 116 | |
119 | - def index | |
120 | - @results = {} | |
121 | - @order = [] | |
122 | - @names = {} | |
123 | - @results_only = true | |
124 | - | |
125 | - @enabled_searches.select { |key,description| @searching[key] }.each do |key, description| | |
126 | - load_query | |
127 | - @asset = key | |
128 | - send(key) | |
129 | - @order << key | |
130 | - @names[key] = getterm(description) | |
131 | - end | |
132 | - @asset = nil | |
133 | - @facets = {} | |
134 | - | |
135 | - render :action => @results.keys.first if @results.keys.size == 1 | |
136 | - end | |
137 | - | |
138 | 117 | # keep old URLs workings |
139 | 118 | def assets |
140 | 119 | params[:action] = params[:asset].is_a?(Array) ? :index : params.delete(:asset) |
141 | 120 | redirect_to params |
142 | 121 | end |
143 | 122 | |
144 | - # view the summary of one category | |
145 | - def category_index | |
146 | - @results = {} | |
147 | - @order = [] | |
148 | - @names = {} | |
149 | - limit = MULTIPLE_SEARCH_LIMIT | |
150 | - [ | |
151 | - [ :people, _('People'), :recent_people ], | |
152 | - [ :enterprises, _('Enterprises'), :recent_enterprises ], | |
153 | - [ :products, _('Products'), :recent_products ], | |
154 | - [ :events, _('Upcoming events'), :upcoming_events ], | |
155 | - [ :communities, _('Communities'), :recent_communities ], | |
156 | - [ :articles, _('Contents'), :recent_articles ] | |
157 | - ].each do |asset, name, filter| | |
158 | - @order << asset | |
159 | - @results[asset] = @category.send(filter, limit) | |
160 | - raise "No total_entries for: #{asset}" unless @results[asset].respond_to?(:total_entries) | |
161 | - @names[asset] = name | |
162 | - end | |
163 | - end | |
164 | - | |
165 | 123 | def tags |
166 | 124 | @tags_cache_key = "tags_env_#{environment.id.to_s}" |
167 | 125 | if is_cache_expired?(@tags_cache_key) |
... | ... | @@ -173,7 +131,7 @@ class SearchController < PublicController |
173 | 131 | @tag = params[:tag] |
174 | 132 | @tag_cache_key = "tag_#{CGI.escape(@tag.to_s)}_env_#{environment.id.to_s}_page_#{params[:npage]}" |
175 | 133 | if is_cache_expired?(@tag_cache_key) |
176 | - @results[@asset] = environment.articles.find_tagged_with(@tag).paginate(paginate_options) | |
134 | + @searches[@asset] = {:results => environment.articles.find_tagged_with(@tag).paginate(paginate_options)} | |
177 | 135 | end |
178 | 136 | end |
179 | 137 | |
... | ... | @@ -187,11 +145,9 @@ class SearchController < PublicController |
187 | 145 | protected |
188 | 146 | |
189 | 147 | def load_query |
190 | - @asset = params[:action].to_sym | |
148 | + @asset = (params[:asset] || params[:action]).to_sym | |
191 | 149 | @order ||= [@asset] |
192 | - @results ||= {} | |
193 | - @filter = filter | |
194 | - @filter_title = filter_description(@asset, @filter) | |
150 | + @searches ||= {} | |
195 | 151 | |
196 | 152 | @query = params[:query] || '' |
197 | 153 | @empty_query = @category.nil? && @query.blank? |
... | ... | @@ -211,42 +167,13 @@ class SearchController < PublicController |
211 | 167 | end |
212 | 168 | end |
213 | 169 | |
214 | - FILTERS = %w( | |
215 | - more_recent | |
216 | - more_active | |
217 | - more_popular | |
218 | - more_comments | |
219 | - ) | |
220 | - def filter | |
221 | - if FILTERS.include?(params[:filter]) | |
222 | - params[:filter] | |
223 | - else | |
224 | - 'more_recent' | |
225 | - end | |
226 | - end | |
227 | - | |
228 | - def filter_description(asset, filter) | |
229 | - { | |
230 | - 'articles_more_recent' => _('More recent contents from network'), | |
231 | - 'articles_more_popular' => _('More viewed contents from network'), | |
232 | - 'articles_more_comments' => _('Most commented contents from network'), | |
233 | - 'people_more_recent' => _('More recent people from network'), | |
234 | - 'people_more_active' => _('More active people from network'), | |
235 | - 'people_more_popular' => _('More popular people from network'), | |
236 | - 'communities_more_recent' => _('More recent communities from network'), | |
237 | - 'communities_more_active' => _('More active communities from network'), | |
238 | - 'communities_more_popular' => _('More popular communities from network'), | |
239 | - 'products_more_recent' => _('Highlights'), | |
240 | - }[asset.to_s + '_' + filter] | |
241 | - end | |
242 | - | |
243 | 170 | def load_search_assets |
244 | - if Searches.keys.include?(params[:action].to_sym) and environment.enabled?("disable_asset_#{params[:action]}") | |
171 | + if SEARCHES.keys.include?(params[:action].to_sym) && environment.enabled?("disable_asset_#{params[:action]}") | |
245 | 172 | render_not_found |
246 | 173 | return |
247 | 174 | end |
248 | 175 | |
249 | - @enabled_searches = Searches.select {|key, name| environment.disabled?("disable_asset_#{params[:action]}") } | |
176 | + @enabled_searches = SEARCHES.select {|key, name| environment.disabled?("disable_asset_#{key}") } | |
250 | 177 | @searching = {} |
251 | 178 | @titles = {} |
252 | 179 | @enabled_searches.each do |key, name| |
... | ... | @@ -256,13 +183,19 @@ class SearchController < PublicController |
256 | 183 | @names = @titles if @names.nil? |
257 | 184 | end |
258 | 185 | |
186 | + def load_filter | |
187 | + @filter = 'more_recent' | |
188 | + if SEARCHES.keys.include?(@asset.to_sym) | |
189 | + available_filters = asset_class(@asset)::SEARCH_FILTERS | |
190 | + @filter = params[:filter] if available_filters.include?(params[:filter]) | |
191 | + end | |
192 | + end | |
193 | + | |
259 | 194 | def limit |
260 | - if map_search? | |
195 | + if map_search?(@searches) | |
261 | 196 | MAP_SEARCH_LIMIT |
262 | 197 | elsif !multiple_search? |
263 | - if [:people, :communities].include? @asset | |
264 | - BLOCKS_SEARCH_LIMIT | |
265 | - elsif @asset == :enterprises and @empty_query | |
198 | + if [:people, :communities, :enterprises].include? @asset | |
266 | 199 | BLOCKS_SEARCH_LIMIT |
267 | 200 | else |
268 | 201 | LIST_SEARCH_LIMIT |
... | ... | @@ -273,41 +206,12 @@ class SearchController < PublicController |
273 | 206 | end |
274 | 207 | |
275 | 208 | def paginate_options(page = params[:page]) |
276 | - page = 1 if multiple_search? or params[:display] == 'map' | |
209 | + page = 1 if multiple_search?(@searches) || params[:display] == 'map' | |
277 | 210 | { :per_page => limit, :page => page } |
278 | 211 | end |
279 | 212 | |
280 | - def full_text_search(filters = [], options = {}) | |
281 | - paginate_options = paginate_options(params[:page]) | |
282 | - asset_class = asset_class(@asset) | |
283 | - solr_options = options | |
284 | - pg_options = paginate_options(params[:page]) | |
285 | - | |
286 | - if !multiple_search? | |
287 | - if !@results_only and asset_class.respond_to? :facets | |
288 | - solr_options.merge! asset_class.facets_find_options(params[:facet]) | |
289 | - solr_options[:all_facets] = true | |
290 | - end | |
291 | - solr_options[:filter_queries] ||= [] | |
292 | - solr_options[:filter_queries] += filters | |
293 | - solr_options[:filter_queries] << "environment_id:#{environment.id}" | |
294 | - solr_options[:filter_queries] << asset_class.facet_category_query.call(@category) if @category | |
295 | - | |
296 | - solr_options[:boost_functions] ||= [] | |
297 | - params[:order_by] = nil if params[:order_by] == 'none' | |
298 | - if params[:order_by] | |
299 | - order = SortOptions[@asset][params[:order_by].to_sym] | |
300 | - raise "Unknown order by" if order.nil? | |
301 | - order[:solr_opts].each do |opt, value| | |
302 | - solr_options[opt] = value.is_a?(Proc) ? instance_eval(&value) : value | |
303 | - end | |
304 | - end | |
305 | - end | |
306 | - | |
307 | - ret = asset_class.find_by_contents(@query, paginate_options, solr_options) | |
308 | - @results[@asset] = ret[:results] | |
309 | - @facets = ret[:facets] | |
310 | - @all_facets = ret[:all_facets] | |
213 | + def full_text_search | |
214 | + @searches[@asset] = find_by_contents(@asset, @scope, @query, paginate_options, {:category => @category, :filter => @filter}) | |
311 | 215 | end |
312 | 216 | |
313 | 217 | private | ... | ... |
app/helpers/application_helper.rb
... | ... | @@ -30,6 +30,12 @@ module ApplicationHelper |
30 | 30 | |
31 | 31 | include AccountHelper |
32 | 32 | |
33 | + include BlogHelper | |
34 | + | |
35 | + include ContentViewerHelper | |
36 | + | |
37 | + include LayoutHelper | |
38 | + | |
33 | 39 | def locale |
34 | 40 | (@page && !@page.language.blank?) ? @page.language : FastGettext.locale |
35 | 41 | end |
... | ... | @@ -260,14 +266,17 @@ module ApplicationHelper |
260 | 266 | end |
261 | 267 | |
262 | 268 | def button_bar(options = {}, &block) |
263 | - concat(content_tag('div', capture(&block) + tag('br', :style => 'clear: left;'), { :class => 'button-bar' }.merge(options))) | |
269 | + options[:class].nil? ? | |
270 | + options[:class]='button-bar' : | |
271 | + options[:class]+=' button-bar' | |
272 | + concat(content_tag('div', capture(&block) + tag('br', :style => 'clear: left;'), options)) | |
264 | 273 | end |
265 | 274 | |
266 | 275 | VIEW_EXTENSIONS = %w[.rhtml .html.erb] |
267 | 276 | |
268 | - def partial_for_class_in_view_path(klass, view_path, suffix = nil) | |
277 | + def partial_for_class_in_view_path(klass, view_path, prefix = nil, suffix = nil) | |
269 | 278 | return nil if klass.nil? |
270 | - name = [klass.name.underscore, suffix].compact.map(&:to_s).join('_') | |
279 | + name = [prefix, klass.name.underscore, suffix].compact.map(&:to_s).join('_') | |
271 | 280 | |
272 | 281 | search_name = String.new(name) |
273 | 282 | if search_name.include?("/") |
... | ... | @@ -282,14 +291,14 @@ module ApplicationHelper |
282 | 291 | return name if File.exists?(File.join(path)) |
283 | 292 | end |
284 | 293 | |
285 | - partial_for_class_in_view_path(klass.superclass, view_path, suffix) | |
294 | + partial_for_class_in_view_path(klass.superclass, view_path, prefix, suffix) | |
286 | 295 | end |
287 | 296 | |
288 | - def partial_for_class(klass, suffix=nil) | |
297 | + def partial_for_class(klass, prefix=nil, suffix=nil) | |
289 | 298 | raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' if klass.nil? |
290 | 299 | name = klass.name.underscore |
291 | 300 | @controller.view_paths.each do |view_path| |
292 | - partial = partial_for_class_in_view_path(klass, view_path, suffix) | |
301 | + partial = partial_for_class_in_view_path(klass, view_path, prefix, suffix) | |
293 | 302 | return partial if partial |
294 | 303 | end |
295 | 304 | |
... | ... | @@ -352,10 +361,6 @@ module ApplicationHelper |
352 | 361 | end |
353 | 362 | end |
354 | 363 | |
355 | - def theme_stylesheet_path | |
356 | - theme_path + '/style.css' | |
357 | - end | |
358 | - | |
359 | 364 | def current_theme |
360 | 365 | @current_theme ||= |
361 | 366 | begin |
... | ... | @@ -493,23 +498,24 @@ module ApplicationHelper |
493 | 498 | |
494 | 499 | def profile_cat_icons( profile ) |
495 | 500 | if profile.class == Enterprise |
496 | - icons = | |
497 | - profile.product_categories.map{ |c| c.size > 1 ? c[1] : nil }. | |
498 | - compact.uniq.map{ |c| | |
499 | - cat_name = c.gsub( /[-_\s,.;'"]+/, '_' ) | |
500 | - cat_icon = "/images/icons-cat/#{cat_name}.png" | |
501 | - if ! File.exists? RAILS_ROOT.to_s() + '/public/' + cat_icon | |
502 | - cat_icon = '/images/icons-cat/undefined.png' | |
503 | - end | |
504 | - content_tag 'span', | |
505 | - content_tag( 'span', c ), | |
506 | - :title => c, | |
507 | - :class => 'product-cat-icon cat_icon_' + cat_name, | |
508 | - :style => "background-image:url(#{cat_icon})" | |
509 | - }.join "\n" | |
510 | - content_tag 'div', | |
511 | - content_tag( 'span', _('Principal Product Categories'), :class => 'header' ) +"\n"+ icons, | |
512 | - :class => 'product-category-icons' | |
501 | + icons = profile.product_categories.map{ |c| c.size > 1 ? c[1] : nil }. | |
502 | + compact.uniq.map do |c| | |
503 | + cat_name = c.gsub( /[-_\s,.;'"]+/, '_' ) | |
504 | + cat_icon = "/images/icons-cat/#{cat_name}.png" | |
505 | + if ! File.exists? RAILS_ROOT.to_s() + '/public/' + cat_icon | |
506 | + cat_icon = '/images/icons-cat/undefined.png' | |
507 | + end | |
508 | + content_tag('span', | |
509 | + content_tag( 'span', c ), | |
510 | + :title => c, | |
511 | + :class => 'product-cat-icon cat_icon_' + cat_name, | |
512 | + :style => "background-image:url(#{cat_icon})" | |
513 | + ) | |
514 | + end.join("\n").html_safe | |
515 | + content_tag('div', | |
516 | + content_tag( 'span', _('Principal Product Categories'), :class => 'header' ) +"\n"+ icons, | |
517 | + :class => 'product-category-icons' | |
518 | + ) | |
513 | 519 | else |
514 | 520 | '' |
515 | 521 | end |
... | ... | @@ -633,10 +639,10 @@ module ApplicationHelper |
633 | 639 | # FIXME |
634 | 640 | ([toplevel] + toplevel.children_for_menu).each do |cat| |
635 | 641 | if cat.top_level? |
636 | - result << '<div class="categorie_box">' | |
642 | + result << '<div class="categorie_box">'.html_safe | |
637 | 643 | result << icon_button( :down, _('open'), '#', :onclick => 'open_close_cat(this); return false' ) |
638 | 644 | result << content_tag('h5', toplevel.name) |
639 | - result << '<div style="display:none"><ul class="categories">' | |
645 | + result << '<div style="display:none"><ul class="categories">'.html_safe | |
640 | 646 | else |
641 | 647 | checkbox_id = "#{object_name}_#{cat.full_name.downcase.gsub(/\s+|\//, '_')}" |
642 | 648 | result << content_tag('li', labelled_check_box( |
... | ... | @@ -647,7 +653,7 @@ module ApplicationHelper |
647 | 653 | :class => ( object.category_ids.include?(cat.id) ? 'cat_checked' : '' ) ) + "\n" |
648 | 654 | end |
649 | 655 | end |
650 | - result << '</ul></div></div>' | |
656 | + result << '</ul></div></div>'.html_safe | |
651 | 657 | end |
652 | 658 | |
653 | 659 | content_tag('div', result) |
... | ... | @@ -787,10 +793,10 @@ module ApplicationHelper |
787 | 793 | :class => 'lineitem' + (line_item+=1).to_s() ) +"\n" |
788 | 794 | if line_item == line_size |
789 | 795 | line_item = 0 |
790 | - html += "<br />\n" | |
796 | + html += "<br />\n".html_safe | |
791 | 797 | end |
792 | 798 | } |
793 | - html += "<br />\n" if line_size == 0 || ( values.size % line_size ) > 0 | |
799 | + html += "<br />\n".html_safe if line_size == 0 || ( values.size % line_size ) > 0 | |
794 | 800 | column = object.class.columns_hash[method.to_s] |
795 | 801 | text = |
796 | 802 | ( column ? |
... | ... | @@ -873,14 +879,6 @@ module ApplicationHelper |
873 | 879 | content_tag('div', labelled_check_box(_('Public'), 'profile_data[fields_privacy]['+name+']', 'public', profile.public_fields.include?(name)), :class => 'field-privacy-selector') |
874 | 880 | end |
875 | 881 | |
876 | - def template_stylesheet_path | |
877 | - if profile.nil? | |
878 | - "/designs/templates/#{environment.layout_template}/stylesheets/style.css" | |
879 | - else | |
880 | - "/designs/templates/#{profile.layout_template}/stylesheets/style.css" | |
881 | - end | |
882 | - end | |
883 | - | |
884 | 882 | def login_url |
885 | 883 | options = Noosfero.url_options.merge({ :controller => 'account', :action => 'login' }) |
886 | 884 | url_for(options) |
... | ... | @@ -919,18 +917,6 @@ module ApplicationHelper |
919 | 917 | end |
920 | 918 | end |
921 | 919 | |
922 | - def icon_theme_stylesheet_path | |
923 | - icon_themes = [] | |
924 | - theme_icon_themes = theme_option(:icon_theme) || [] | |
925 | - for icon_theme in theme_icon_themes do | |
926 | - theme_path = "/designs/icons/#{icon_theme}/style.css" | |
927 | - if File.exists?(File.join(RAILS_ROOT, 'public', theme_path)) | |
928 | - icon_themes << theme_path | |
929 | - end | |
930 | - end | |
931 | - icon_themes | |
932 | - end | |
933 | - | |
934 | 920 | def page_title |
935 | 921 | (@page ? @page.title + ' - ' : '') + |
936 | 922 | (profile ? profile.short_name + ' - ' : '') + |
... | ... | @@ -942,42 +928,13 @@ module ApplicationHelper |
942 | 928 | (@category ? " - #{@category.full_name}" : '') |
943 | 929 | end |
944 | 930 | |
945 | - def noosfero_javascript | |
946 | - render :file => 'layouts/_javascript' | |
947 | - end | |
948 | - | |
949 | - def noosfero_stylesheets | |
950 | - [ | |
951 | - 'application', | |
952 | - 'search', | |
953 | - 'thickbox', | |
954 | - 'lightbox', | |
955 | - 'colorpicker', | |
956 | - 'colorbox', | |
957 | - pngfix_stylesheet_path, | |
958 | - ] + | |
959 | - tokeninput_stylesheets | |
960 | - end | |
961 | - | |
962 | 931 | # DEPRECATED. Do not use this· |
963 | 932 | def import_controller_stylesheets(options = {}) |
964 | 933 | stylesheet_import( "controller_"+ @controller.controller_name(), options ) |
965 | 934 | end |
966 | 935 | |
967 | - def pngfix_stylesheet_path | |
968 | - 'iepngfix/iepngfix.css' | |
969 | - end | |
970 | - | |
971 | - def tokeninput_stylesheets | |
972 | - ['token-input', 'token-input-facebook', 'token-input-mac', 'token-input-facet'] | |
973 | - end | |
974 | - | |
975 | - def noosfero_layout_features | |
976 | - render :file => 'shared/noosfero_layout_features' | |
977 | - end | |
978 | - | |
979 | 936 | def link_to_email(email) |
980 | - javascript_tag('var array = ' + email.split('@').to_json + '; document.write("<a href=\'mailto:" + array.join("@") + "\'>" + array.join("@") + "</a>")') | |
937 | + javascript_tag('var array = ' + email.split('@').to_json + '; document.write("<a href=\'mailto:" + array.join("@") + "\'>" + array.join("@") + "</a>")'.html_safe) | |
981 | 938 | end |
982 | 939 | |
983 | 940 | def stylesheet(*args) |
... | ... | @@ -987,13 +944,43 @@ module ApplicationHelper |
987 | 944 | def article_to_html(article, options = {}) |
988 | 945 | options.merge!(:page => params[:npage]) |
989 | 946 | content = article.to_html(options) |
990 | - content = content.kind_of?(Proc) ? self.instance_eval(&content) : content | |
947 | + content = content.kind_of?(Proc) ? self.instance_eval(&content).html_safe : content.html_safe | |
991 | 948 | @plugins && @plugins.each do |plugin| |
992 | 949 | content = plugin.parse_content(content) |
993 | 950 | end |
994 | 951 | content |
995 | 952 | end |
996 | 953 | |
954 | + # Please, use link_to by default! | |
955 | + # This method was created to work around to inexplicable | |
956 | + # chain of problems when display_short_format was called | |
957 | + # from Article model for an ArticleBlock. | |
958 | + def reference_to_article(text, article, anchor=nil) | |
959 | + if article.profile.domains.empty? | |
960 | + href = "/#{article.url[:profile]}/" | |
961 | + else | |
962 | + href = "http://#{article.profile.domains.first.name}/" | |
963 | + end | |
964 | + href += article.url[:page].join('/') | |
965 | + href += '#' + anchor if anchor | |
966 | + content_tag('a', text, :href => href) | |
967 | + end | |
968 | + | |
969 | + def display_short_format(article, options={}) | |
970 | + options[:comments_link] ||= true | |
971 | + options[:read_more_link] ||= true | |
972 | + html = content_tag('div', | |
973 | + article.lead + | |
974 | + content_tag('div', | |
975 | + (options[:comments_link] ? link_to_comments(article) : '') + | |
976 | + (options[:read_more_link] ? reference_to_article( _('Read more'), article) : ''), | |
977 | + :class => 'read-more' | |
978 | + ), | |
979 | + :class => 'short-post' | |
980 | + ) | |
981 | + html | |
982 | + end | |
983 | + | |
997 | 984 | def colorpicker_field(object_name, method, options = {}) |
998 | 985 | text_field(object_name, method, options.merge(:class => 'colorpicker_field')) |
999 | 986 | end |
... | ... | @@ -1003,7 +990,7 @@ module ApplicationHelper |
1003 | 990 | end |
1004 | 991 | |
1005 | 992 | def ui_icon(icon_class, extra_class = '') |
1006 | - "<span class='ui-icon #{icon_class} #{extra_class}' style='float:left; margin-right:7px;'></span>" | |
993 | + "<span class='ui-icon #{icon_class} #{extra_class}' style='float:left; margin-right:7px;'></span>".html_safe | |
1007 | 994 | end |
1008 | 995 | |
1009 | 996 | def ui_button(label, url, html_options = {}) |
... | ... | @@ -1018,10 +1005,6 @@ module ApplicationHelper |
1018 | 1005 | theme_option(:jquery_theme) || 'smoothness_mod' |
1019 | 1006 | end |
1020 | 1007 | |
1021 | - def jquery_ui_theme_stylesheet_path | |
1022 | - 'jquery.ui/' + jquery_theme + '/jquery-ui-1.8.2.custom' | |
1023 | - end | |
1024 | - | |
1025 | 1008 | def ui_error(message) |
1026 | 1009 | content_tag('div', ui_icon('ui-icon-alert') + message, :class => 'alert fg-state-error ui-state-error') |
1027 | 1010 | end |
... | ... | @@ -1035,13 +1018,13 @@ module ApplicationHelper |
1035 | 1018 | end |
1036 | 1019 | |
1037 | 1020 | def collapsed_item_icon |
1038 | - "<span class='ui-icon ui-icon-circlesmall-plus' style='float:left;'></span>" | |
1021 | + "<span class='ui-icon ui-icon-circlesmall-plus' style='float:left;'></span>".html_safe | |
1039 | 1022 | end |
1040 | 1023 | def expanded_item_icon |
1041 | - "<span class='ui-icon ui-icon-circlesmall-minus' style='float:left;'></span>" | |
1024 | + "<span class='ui-icon ui-icon-circlesmall-minus' style='float:left;'></span>".html_safe | |
1042 | 1025 | end |
1043 | 1026 | def leaf_item_icon |
1044 | - "<span class='ui-icon ui-icon-arrow-1-e' style='float:left;'></span>" | |
1027 | + "<span class='ui-icon ui-icon-arrow-1-e' style='float:left;'></span>".html_safe | |
1045 | 1028 | end |
1046 | 1029 | |
1047 | 1030 | def display_category_menu(block, categories, root = true) |
... | ... | @@ -1300,9 +1283,7 @@ module ApplicationHelper |
1300 | 1283 | titles = tabs.inject(''){ |result, tab| result << content_tag(:li, link_to(tab[:title], '#'+tab[:id]), :class => 'tab') } |
1301 | 1284 | contents = tabs.inject(''){ |result, tab| result << content_tag(:div, tab[:content], :id => tab[:id]) } |
1302 | 1285 | |
1303 | - content_tag :div, :class => 'ui-tabs' do | |
1304 | - content_tag(:ul, titles) + contents | |
1305 | - end | |
1286 | + content_tag(:div, content_tag(:ul, titles) + raw(contents), :class => 'ui-tabs') | |
1306 | 1287 | end |
1307 | 1288 | |
1308 | 1289 | def jquery_token_input_messages_json(hintText = _('Type in an keyword'), noResultsText = _('No results'), searchingText = _('Searching...')) |
... | ... | @@ -1331,11 +1312,12 @@ module ApplicationHelper |
1331 | 1312 | end |
1332 | 1313 | |
1333 | 1314 | def template_options(klass, field_name) |
1334 | - return '' if klass.templates.count == 0 | |
1335 | - return hidden_field_tag("#{field_name}[template_id]", klass.templates.first.id) if klass.templates.count == 1 | |
1315 | + templates = klass.templates(environment) | |
1316 | + return '' if templates.count == 0 | |
1317 | + return hidden_field_tag("#{field_name}[template_id]", templates.first.id) if templates.count == 1 | |
1336 | 1318 | |
1337 | 1319 | counter = 0 |
1338 | - radios = klass.templates.map do |template| | |
1320 | + radios = templates.map do |template| | |
1339 | 1321 | counter += 1 |
1340 | 1322 | content_tag('li', labelled_radio_button(link_to(template.name, template.url, :target => '_blank'), "#{field_name}[template_id]", template.id, counter==1)) |
1341 | 1323 | end.join("\n") |
... | ... | @@ -1425,4 +1407,14 @@ module ApplicationHelper |
1425 | 1407 | @no_design_blocks = true |
1426 | 1408 | end |
1427 | 1409 | |
1410 | + def default_folder_for_image_upload(profile) | |
1411 | + default_folder = profile.folders.find_by_type('Gallery') | |
1412 | + default_folder = profile.folders.find_by_type('Folder') if default_folder.nil? | |
1413 | + default_folder | |
1414 | + end | |
1415 | + | |
1416 | + def content_id_to_str(content) | |
1417 | + content.nil? ? '' : content.id.to_s | |
1418 | + end | |
1419 | + | |
1428 | 1420 | end | ... | ... |
app/helpers/block_helper.rb
... | ... | @@ -3,7 +3,24 @@ module BlockHelper |
3 | 3 | def block_title(title) |
4 | 4 | tag_class = 'block-title' |
5 | 5 | tag_class += ' empty' if title.empty? |
6 | - content_tag 'h3', content_tag('span', title), :class => tag_class | |
6 | + content_tag 'h3', content_tag('span', h(title)), :class => tag_class | |
7 | + end | |
8 | + | |
9 | + def highlights_block_config_image_fields(block, image={}) | |
10 | + " | |
11 | + <tr class=\"image-data-line\"> | |
12 | + <td> | |
13 | + #{select_tag 'block[images][][image_id]', content_tag(:option) + option_groups_from_collection_for_select(block.folder_choices, :images, :name, :id, :name, image[:image_id].to_i).html_safe} | |
14 | + </td> | |
15 | + <td>#{text_field_tag 'block[images][][address]', image[:address], :class => 'highlight-address', :size => 20}</td> | |
16 | + <td>#{text_field_tag 'block[images][][position]', image[:position], :class => 'highlight-position', :size => 1}</td> | |
17 | + </tr><tr class=\"image-title\"> | |
18 | + <td colspan=\"3\"><label>#{ | |
19 | + content_tag('span', _('Title')) + | |
20 | + text_field_tag('block[images][][title]', image[:title], :class => 'highlight-title', :size => 45) | |
21 | + }</label></td> | |
22 | + </tr> | |
23 | + " | |
7 | 24 | end |
8 | 25 | |
9 | 26 | end | ... | ... |
app/helpers/blog_helper.rb
... | ... | @@ -18,8 +18,9 @@ module BlogHelper |
18 | 18 | pagination = will_paginate(articles, { |
19 | 19 | :param_name => 'npage', |
20 | 20 | :previous_label => _('« Newer posts'), |
21 | - :next_label => _('Older posts »') | |
22 | - }) | |
21 | + :next_label => _('Older posts »'), | |
22 | + :params => {:action=>"view_page", :page=>articles.first.parent.path.split('/'), :controller=>"content_viewer"} | |
23 | + }) if articles.present? | |
23 | 24 | content = [] |
24 | 25 | artic_len = articles.length |
25 | 26 | articles.each_with_index{ |art,i| |
... | ... | @@ -31,7 +32,7 @@ module BlogHelper |
31 | 32 | css_add << position + '-inner' |
32 | 33 | content << content_tag('div', |
33 | 34 | content_tag('div', |
34 | - display_post(art, format) + '<br style="clear:both"/>', | |
35 | + display_post(art, format).html_safe + '<br style="clear:both"/>'.html_safe, | |
35 | 36 | :class => 'blog-post ' + css_add.join(' '), |
36 | 37 | :id => "post-#{art.id}"), :class => position |
37 | 38 | ) |
... | ... | @@ -46,18 +47,6 @@ module BlogHelper |
46 | 47 | article_title(article, :no_comments => no_comments) + html |
47 | 48 | end |
48 | 49 | |
49 | - def display_short_format(article) | |
50 | - html = content_tag('div', | |
51 | - article.lead + | |
52 | - content_tag('div', | |
53 | - link_to_comments(article) + | |
54 | - link_to( _('Read more'), article.url), | |
55 | - :class => 'read-more'), | |
56 | - :class => 'short-post' | |
57 | - ) | |
58 | - html | |
59 | - end | |
60 | - | |
61 | 50 | def display_full_format(article) |
62 | 51 | html = article_to_html(article) |
63 | 52 | html = content_tag('p', html) if ! html.include?('</p>') | ... | ... |
app/helpers/catalog_helper.rb
... | ... | @@ -21,7 +21,7 @@ module CatalogHelper |
21 | 21 | |
22 | 22 | def category_sub_links(category) |
23 | 23 | sub_categories = [] |
24 | - category.children.each do |sub_category| | |
24 | + category.children.order(:name).each do |sub_category| | |
25 | 25 | sub_categories << category_link(sub_category, true) |
26 | 26 | end |
27 | 27 | content_tag('ul', sub_categories) if sub_categories.size > 1 | ... | ... |
app/helpers/content_viewer_helper.rb
... | ... | @@ -39,7 +39,7 @@ module ContentViewerHelper |
39 | 39 | |
40 | 40 | def link_to_comments(article, args = {}) |
41 | 41 | return '' unless article.accept_comments? |
42 | - link_to(number_of_comments(article), article.url.merge(:anchor => 'comments_list') ) | |
42 | + reference_to_article number_of_comments(article), article, 'comments_list' | |
43 | 43 | end |
44 | 44 | |
45 | 45 | def article_translations(article) |
... | ... | @@ -48,7 +48,7 @@ module ContentViewerHelper |
48 | 48 | { article.environment.locales[translation.language] => { :href => url_for(translation.url) } } |
49 | 49 | end |
50 | 50 | content_tag(:div, link_to(_('Translations'), '#', |
51 | - :onclick => "toggleSubmenu(this, '#{_('Translations')}', #{links.to_json}); return false", | |
51 | + :onmouseover => "toggleSubmenu(this, '#{_('Translations')}', #{links.to_json}); return false", | |
52 | 52 | :class => 'article-translations-menu simplemenu-trigger up'), |
53 | 53 | :class => 'article-translations') |
54 | 54 | end | ... | ... |
app/helpers/dates_helper.rb
... | ... | @@ -23,11 +23,13 @@ module DatesHelper |
23 | 23 | end |
24 | 24 | |
25 | 25 | # formats a date for displaying. |
26 | - def show_date(date, use_numbers = false) | |
26 | + def show_date(date, use_numbers = false, year=true) | |
27 | 27 | if date && use_numbers |
28 | - _('%{month}/%{day}/%{year}') % { :day => date.day, :month => date.month, :year => date.year } | |
28 | + date_format = year ? _('%{month}/%{day}/%{year}') : _('%{month}/%{day}') | |
29 | + date_format % { :day => date.day, :month => date.month, :year => date.year } | |
29 | 30 | elsif date |
30 | - _('%{month} %{day}, %{year}') % { :day => date.day, :month => month_name(date.month), :year => date.year } | |
31 | + date_format = year ? _('%{month_name} %{day}, %{year}') : _('%{month_name} %{day}') | |
32 | + date_format % { :day => date.day, :month_name => month_name(date.month), :year => date.year } | |
31 | 33 | else |
32 | 34 | '' |
33 | 35 | end |
... | ... | @@ -46,7 +48,27 @@ module DatesHelper |
46 | 48 | if (date1 == date2) || (date2.nil?) |
47 | 49 | show_date(date1, use_numbers) |
48 | 50 | else |
49 | - _('from %{date1} to %{date2}') % {:date1 => show_date(date1, use_numbers), :date2 => show_date(date2, use_numbers)} | |
51 | + if date1.year == date2.year | |
52 | + if date1.month == date2.month | |
53 | + _('from %{month} %{day1} to %{day2}, %{year}') % { | |
54 | + :day1 => date1.day, | |
55 | + :day2 => date2.day, | |
56 | + :month => use_numbers ? date1.month : month_name(date1.month), | |
57 | + :year => date1.year | |
58 | + } | |
59 | + else | |
60 | + _('from %{date1} to %{date2}, %{year}') % { | |
61 | + :date1 => show_date(date1, use_numbers, false), | |
62 | + :date2 => show_date(date2, use_numbers, false), | |
63 | + :year => date1.year | |
64 | + } | |
65 | + end | |
66 | + else | |
67 | + _('from %{date1} to %{date2}') % { | |
68 | + :date1 => show_date(date1, use_numbers), | |
69 | + :date2 => show_date(date2, use_numbers) | |
70 | + } | |
71 | + end | |
50 | 72 | end |
51 | 73 | end |
52 | 74 | ... | ... |
app/helpers/forms_helper.rb
... | ... | @@ -142,38 +142,6 @@ module FormsHelper |
142 | 142 | content_tag('table',rows.join("\n")) |
143 | 143 | end |
144 | 144 | |
145 | - def select_folder(label_text, field_id, collection, default_value=nil, html_options = {}, js_options = {}) | |
146 | - root = profile ? profile.identifier : _("root") | |
147 | - labelled_form_field( | |
148 | - label_text, | |
149 | - select_tag( | |
150 | - field_id, | |
151 | - options_for_select( | |
152 | - [[root, '']] + | |
153 | - collection.collect {|f| [ root + '/' + f.full_name, f.id ] }, | |
154 | - default_value | |
155 | - ), | |
156 | - html_options.merge(js_options) | |
157 | - ) | |
158 | - ) | |
159 | - end | |
160 | - | |
161 | - def select_profile_folder(label_text, field_id, profile, default_value='', html_options = {}, js_options = {}) | |
162 | - result = labelled_form_field( | |
163 | - label_text, | |
164 | - select_tag( | |
165 | - field_id, | |
166 | - options_for_select( | |
167 | - [[profile.identifier, '']] + | |
168 | - profile.folders.collect {|f| [ profile.identifier + '/' + f.full_name, f.id ] }, | |
169 | - default_value | |
170 | - ), | |
171 | - html_options.merge(js_options) | |
172 | - ) | |
173 | - ) | |
174 | - return result | |
175 | - end | |
176 | - | |
177 | 145 | def date_field(name, value, format = '%Y-%m-%d', datepicker_options = {}, html_options = {}) |
178 | 146 | datepicker_options[:disabled] ||= false |
179 | 147 | datepicker_options[:alt_field] ||= '' |
... | ... | @@ -276,7 +244,7 @@ module FormsHelper |
276 | 244 | yearSuffix: #{datepicker_options[:year_suffix].to_json} |
277 | 245 | }) |
278 | 246 | </script> |
279 | - " | |
247 | + ".html_safe | |
280 | 248 | result |
281 | 249 | end |
282 | 250 | |
... | ... | @@ -295,23 +263,28 @@ module FormsHelper |
295 | 263 | field_id, |
296 | 264 | options_for_select( |
297 | 265 | [[root, '']] + |
298 | - collection.collect {|f| [ root + '/' + f.full_name, f.id ] }, | |
299 | - default_value | |
266 | + collection.collect {|f| [ root + '/' + f.full_name, f.id.to_s ] }, | |
267 | + default_value.to_s | |
300 | 268 | ), |
301 | 269 | html_options.merge(js_options) |
302 | 270 | ) |
303 | 271 | ) |
304 | 272 | end |
305 | 273 | |
306 | - def select_profile_folder(label_text, field_id, profile, default_value='', html_options = {}, js_options = {}) | |
274 | + def select_profile_folder(label_text, field_id, profile, default_value='', html_options = {}, js_options = {}, find_options = {}) | |
275 | + if find_options.empty? | |
276 | + folders = profile.folders | |
277 | + else | |
278 | + folders = profile.folders.where(find_options) | |
279 | + end | |
307 | 280 | result = labelled_form_field( |
308 | 281 | label_text, |
309 | 282 | select_tag( |
310 | 283 | field_id, |
311 | 284 | options_for_select( |
312 | 285 | [[profile.identifier, '']] + |
313 | - profile.folders.collect {|f| [ profile.identifier + '/' + f.full_name, f.id ] }, | |
314 | - default_value | |
286 | + folders.collect {|f| [ profile.identifier + '/' + f.full_name, f.id.to_s ] }, | |
287 | + default_value.to_s | |
315 | 288 | ), |
316 | 289 | html_options.merge(js_options) |
317 | 290 | ) | ... | ... |
... | ... | @@ -0,0 +1,94 @@ |
1 | +module LayoutHelper | |
2 | + | |
3 | + def body_classes | |
4 | + # Identify the current controller and action for the CSS: | |
5 | + " controller-#{@controller.controller_name}" + | |
6 | + " action-#{@controller.controller_name}-#{@controller.action_name}" + | |
7 | + " template-#{profile.nil? ? "default" : profile.layout_template}" + | |
8 | + (!profile.nil? && profile.is_on_homepage?(request.path,@page) ? " profile-homepage" : "") | |
9 | + end | |
10 | + | |
11 | + def noosfero_javascript | |
12 | + plugins_javascripts = @plugins.map { |plugin| plugin.js_files.map { |js| plugin.class.public_path(js) } }.flatten | |
13 | + | |
14 | + output = '' | |
15 | + output += render :file => 'layouts/_javascript' | |
16 | + output += javascript_tag 'render_all_jquery_ui_widgets()' | |
17 | + unless plugins_javascripts.empty? | |
18 | + output += javascript_include_tag plugins_javascripts, :cache => "cache/plugins-#{Digest::MD5.hexdigest plugins_javascripts.to_s}" | |
19 | + end | |
20 | + output | |
21 | + end | |
22 | + | |
23 | + def noosfero_stylesheets | |
24 | + standard_stylesheets = [ | |
25 | + 'application', | |
26 | + 'search', | |
27 | + 'thickbox', | |
28 | + 'lightbox', | |
29 | + 'colorpicker', | |
30 | + 'colorbox', | |
31 | + pngfix_stylesheet_path, | |
32 | + ] + tokeninput_stylesheets | |
33 | + plugins_stylesheets = @plugins.select(&:stylesheet?).map { |plugin| plugin.class.public_path('style.css') } | |
34 | + | |
35 | + output = '' | |
36 | + output += stylesheet_link_tag standard_stylesheets, :cache => 'cache' | |
37 | + output += stylesheet_link_tag template_stylesheet_path | |
38 | + output += stylesheet_link_tag icon_theme_stylesheet_path | |
39 | + output += stylesheet_link_tag jquery_ui_theme_stylesheet_path | |
40 | + unless plugins_stylesheets.empty? | |
41 | + output += stylesheet_link_tag plugins_stylesheets, :cache => "cache/plugins-#{Digest::MD5.hexdigest plugins_stylesheets.to_s}" | |
42 | + end | |
43 | + output += stylesheet_link_tag theme_stylesheet_path | |
44 | + output | |
45 | + end | |
46 | + | |
47 | + def pngfix_stylesheet_path | |
48 | + 'iepngfix/iepngfix.css' | |
49 | + end | |
50 | + | |
51 | + def tokeninput_stylesheets | |
52 | + ['token-input', 'token-input-facebook', 'token-input-mac', 'token-input-facet'] | |
53 | + end | |
54 | + | |
55 | + def noosfero_layout_features | |
56 | + render :file => 'shared/noosfero_layout_features' | |
57 | + end | |
58 | + | |
59 | + def template_stylesheet_path | |
60 | + if profile.nil? | |
61 | + "/designs/templates/#{environment.layout_template}/stylesheets/style.css" | |
62 | + else | |
63 | + "/designs/templates/#{profile.layout_template}/stylesheets/style.css" | |
64 | + end | |
65 | + end | |
66 | + | |
67 | + def icon_theme_stylesheet_path | |
68 | + icon_themes = [] | |
69 | + theme_icon_themes = theme_option(:icon_theme) || [] | |
70 | + for icon_theme in theme_icon_themes do | |
71 | + theme_path = "/designs/icons/#{icon_theme}/style.css" | |
72 | + if File.exists?(File.join(RAILS_ROOT, 'public', theme_path)) | |
73 | + icon_themes << theme_path | |
74 | + end | |
75 | + end | |
76 | + icon_themes | |
77 | + end | |
78 | + | |
79 | + def jquery_ui_theme_stylesheet_path | |
80 | + 'jquery.ui/' + jquery_theme + '/jquery-ui-1.8.2.custom' | |
81 | + end | |
82 | + | |
83 | + def theme_stylesheet_path | |
84 | + theme_path + '/style.css' | |
85 | + end | |
86 | + | |
87 | + def addthis_javascript | |
88 | + if NOOSFERO_CONF['addthis_enabled'] | |
89 | + '<script src="http://s7.addthis.com/js/152/addthis_widget.js"></script>' | |
90 | + end | |
91 | + end | |
92 | + | |
93 | +end | |
94 | + | ... | ... |
app/helpers/profile_editor_helper.rb
... | ... | @@ -136,7 +136,7 @@ module ProfileEditorHelper |
136 | 136 | concat( |
137 | 137 | content_tag( |
138 | 138 | 'div', |
139 | - capture(&block) + '<br style="clear:left;"/> ', | |
139 | + capture(&block) + content_tag('br', '', :style => 'clear: left'), | |
140 | 140 | :class => 'control-panel') |
141 | 141 | ) |
142 | 142 | end | ... | ... |
app/helpers/search_helper.rb
... | ... | @@ -2,12 +2,10 @@ module SearchHelper |
2 | 2 | |
3 | 3 | MAP_SEARCH_LIMIT = 2000 |
4 | 4 | LIST_SEARCH_LIMIT = 20 |
5 | - BLOCKS_SEARCH_LIMIT = 18 | |
5 | + BLOCKS_SEARCH_LIMIT = 24 | |
6 | 6 | MULTIPLE_SEARCH_LIMIT = 8 |
7 | - DistFilt = 200 | |
8 | - DistBoost = 50 | |
9 | 7 | |
10 | - Searches = ActiveSupport::OrderedHash[ | |
8 | + SEARCHES = ActiveSupport::OrderedHash[ | |
11 | 9 | :articles, _('Contents'), |
12 | 10 | :enterprises, _('Enterprises'), |
13 | 11 | :people, _('People'), |
... | ... | @@ -16,46 +14,31 @@ module SearchHelper |
16 | 14 | :events, _('Events'), |
17 | 15 | ] |
18 | 16 | |
19 | - SortOptions = { | |
20 | - :products => ActiveSupport::OrderedHash[ :none, {:label => _('Relevance')}, | |
21 | - :more_recent, {:label => _('More recent'), :solr_opts => {:sort => 'updated_at desc, score desc'}}, | |
22 | - :name, {:label => _('Name'), :solr_opts => {:sort => 'name_sortable asc'}}, | |
23 | - :closest, {:label => _('Closest to me'), :if => proc{ logged_in? && (profile=current_user.person).lat && profile.lng }, | |
24 | - :solr_opts => {:sort => "geodist() asc", | |
25 | - :latitude => proc{ current_user.person.lat }, :longitude => proc{ current_user.person.lng }}}, | |
26 | - ], | |
27 | - :events => ActiveSupport::OrderedHash[ :none, {:label => _('Relevance')}, | |
28 | - :name, {:label => _('Name'), :solr_opts => {:sort => 'name_sortable asc'}}, | |
29 | - ], | |
30 | - :articles => ActiveSupport::OrderedHash[ :none, {:label => _('Relevance')}, | |
31 | - :name, {:label => _('Name'), :solr_opts => {:sort => 'name_sortable asc'}}, | |
32 | - :more_recent, {:label => _('More recent'), :solr_opts => {:sort => 'updated_at desc, score desc'}}, | |
33 | - ], | |
34 | - :enterprises => ActiveSupport::OrderedHash[ :none, {:label => _('Relevance')}, | |
35 | - :name, {:label => _('Name'), :solr_opts => {:sort => 'name_sortable asc'}}, | |
36 | - ], | |
37 | - :people => ActiveSupport::OrderedHash[ :none, {:label => _('Relevance')}, | |
38 | - :name, {:label => _('Name'), :solr_opts => {:sort => 'name_sortable asc'}}, | |
39 | - ], | |
40 | - :communities => ActiveSupport::OrderedHash[ :none, {:label => _('Relevance')}, | |
41 | - :name, {:label => _('Name'), :solr_opts => {:sort => 'name_sortable asc'}}, | |
42 | - ], | |
17 | + FILTER_TRANSLATION = { | |
18 | + 'more_popular' => _('More popular'), | |
19 | + 'more_active' => _('More active'), | |
20 | + 'more_recent' => _('More recent'), | |
21 | + 'more_comments' => _('More comments') | |
43 | 22 | } |
44 | 23 | |
45 | 24 | # FIXME remove it after search_controler refactored |
46 | 25 | include EventsHelper |
47 | 26 | |
48 | - def multiple_search? | |
49 | - ['index', 'category_index'].include?(params[:action]) or @results.size > 1 | |
27 | + def multiple_search?(searches=nil) | |
28 | + ['index', 'category_index'].include?(params[:action]) || (searches && searches.size > 1) | |
50 | 29 | end |
51 | 30 | |
52 | - def map_search? | |
53 | - !@empty_query and !multiple_search? and params[:display] == 'map' | |
31 | + def map_search?(searches=nil) | |
32 | + !multiple_search?(searches) && params[:display] == 'map' | |
33 | + end | |
34 | + | |
35 | + def asset_class(asset) | |
36 | + asset.to_s.singularize.camelize.constantize | |
54 | 37 | end |
55 | 38 | |
56 | 39 | def search_page_title(title, category = nil) |
57 | 40 | title = "<h1>" + title |
58 | - title += '<small>' + category.name + '</small>' if category | |
41 | + title += ' - <small>' + category.name + '</small>' if category | |
59 | 42 | title + "</h1>" |
60 | 43 | end |
61 | 44 | |
... | ... | @@ -66,8 +49,12 @@ module SearchHelper |
66 | 49 | :align => 'center', :class => 'search-category-context') if category |
67 | 50 | end |
68 | 51 | |
69 | - def display_results(map_capable = false) | |
70 | - if map_capable and map_search? | |
52 | + def display?(asset, mode) | |
53 | + defined?(asset_class(asset)::SEARCH_DISPLAYS) && asset_class(asset)::SEARCH_DISPLAYS.include?(mode.to_s) | |
54 | + end | |
55 | + | |
56 | + def display_results(searches=nil, asset=nil) | |
57 | + if display?(asset, :map) && map_search?(searches) | |
71 | 58 | partial = 'google_maps' |
72 | 59 | klass = 'map' |
73 | 60 | else |
... | ... | @@ -78,10 +65,13 @@ module SearchHelper |
78 | 65 | content_tag('div', render(:partial => partial), :class => "map-or-list-search-results #{klass}") |
79 | 66 | end |
80 | 67 | |
81 | - def display_map_list_button | |
82 | - button(:search, params[:display] == 'map' ? _('Display in list') : _('Display in map'), | |
83 | - params.merge(:display => (params[:display] == 'map' ? 'list' : 'map')), | |
84 | - :class => "map-toggle-button" ) | |
68 | + def display_filter(asset, display) | |
69 | + asset = :articles if asset == :tag | |
70 | + if display?(asset, display) | |
71 | + display | |
72 | + else | |
73 | + asset_class(asset).default_search_display | |
74 | + end | |
85 | 75 | end |
86 | 76 | |
87 | 77 | def city_with_state(city) |
... | ... | @@ -97,120 +87,50 @@ module SearchHelper |
97 | 87 | end |
98 | 88 | end |
99 | 89 | |
100 | - def facets_menu(asset, _facets) | |
101 | - @asset_class = asset_class(asset) | |
102 | - @facets = _facets | |
103 | - render(:partial => 'facets_menu') | |
104 | - end | |
105 | - | |
106 | - def facets_unselect_menu(asset) | |
107 | - @asset_class = asset_class(asset) | |
108 | - render(:partial => 'facets_unselect_menu') | |
109 | - end | |
110 | - | |
111 | - def facet_javascript(input_id, facet, array) | |
112 | - array = [] if array.nil? | |
113 | - hintText = _('Type in an option') | |
114 | - text_field_tag('facet['+input_id+']', '', :id => input_id) + | |
115 | - javascript_tag("jQuery.TokenList(jQuery('##{input_id}'), #{array.to_json}, | |
116 | - {searchDelay: 0, permanentDropdown: true, theme: 'facet', dontAdd: true, preventDuplicates: true, | |
117 | - #{jquery_token_input_messages_json(hintText)}});") | |
118 | - end | |
119 | - | |
120 | - def facet_link_html(facet, params, value, label, count) | |
121 | - params = params ? params.dup : {} | |
122 | - has_extra = label.kind_of?(Array) | |
123 | - link_label = has_extra ? label[0] : label | |
124 | - id = facet[:solr_field].to_s | |
125 | - params[:facet] ||= {} | |
126 | - params[:facet][id] ||= {} | |
127 | - params[:page] = {} if params[:page] | |
128 | - | |
129 | - selected = facet[:label_id].nil? ? params[:facet][id] == value : params[:facet][id][facet[:label_id]].to_a.include?(value) | |
130 | - | |
131 | - if count > 0 | |
132 | - url = params.merge(:facet => params[:facet].merge( | |
133 | - id => facet[:label_id].nil? ? value : params[:facet][id].merge( facet[:label_id] => params[:facet][id][facet[:label_id]].to_a | [value] ) | |
134 | - )) | |
135 | - else | |
136 | - # preserve others filters and change this filter | |
137 | - url = params.merge(:facet => params[:facet].merge( | |
138 | - id => facet[:label_id].nil? ? value : { facet[:label_id] => value } | |
139 | - )) | |
90 | + def display_selector(asset, display, float = 'right') | |
91 | + display = nil if display.blank? | |
92 | + display ||= asset_class(asset).default_search_display | |
93 | + if [display?(asset, :map), display?(asset, :compact), display?(asset, :full)].select {|option| option}.count > 1 | |
94 | + compact_link = display?(asset, :compact) ? (display == 'compact' ? _('Compact') : link_to(_('Compact'), params.merge(:display => 'compact'))) : nil | |
95 | + map_link = display?(asset, :map) ? (display == 'map' ? _('Map') : link_to(_('Map'), params.merge(:display => 'map'))) : nil | |
96 | + full_link = display?(asset, :full) ? (display == 'full' ? _('Full') : link_to(_('Full'), params.merge(:display => 'full'))) : nil | |
97 | + content_tag('div', | |
98 | + content_tag('strong', _('Display')) + ': ' + [compact_link, map_link, full_link].compact.join(' | ').html_safe, | |
99 | + :class => 'search-customize-options' | |
100 | + ) | |
140 | 101 | end |
141 | - | |
142 | - content_tag 'div', link_to(link_label, url, :class => 'facet-result-link-label') + | |
143 | - content_tag('span', (has_extra ? label[1] : ''), :class => 'facet-result-extra-label') + | |
144 | - (count > 0 ? content_tag('span', " (#{count})", :class => 'facet-result-count') : ''), | |
145 | - :class => 'facet-menu-item' + (selected ? ' facet-result-link-selected' : '') | |
146 | 102 | end |
147 | 103 | |
148 | - def facet_selecteds_html_for(environment, klass, params) | |
149 | - def name_with_extra(klass, facet, value) | |
150 | - name = klass.facet_result_name(facet, value) | |
151 | - name = name[0] + name[1] if name.kind_of?(Array) | |
152 | - name | |
153 | - end | |
154 | - | |
155 | - ret = [] | |
156 | - params = params.dup | |
157 | - params[:facet].each do |id, value| | |
158 | - facet = klass.facet_by_id(id.to_sym) | |
159 | - next unless facet | |
160 | - if value.kind_of?(Hash) | |
161 | - label_hash = facet[:label].call(environment) | |
162 | - value.each do |label_id, value| | |
163 | - facet[:label_id] = label_id | |
164 | - facet[:label] = label_hash[label_id] | |
165 | - value.to_a.each do |value| | |
166 | - ret << [facet[:label], name_with_extra(klass, facet, value), | |
167 | - params.merge(:facet => params[:facet].merge(id => params[:facet][id].merge(label_id => params[:facet][id][label_id].to_a.reject{ |v| v == value })))] | |
168 | - end | |
169 | - end | |
170 | - else | |
171 | - ret << [klass.facet_label(facet), name_with_extra(klass, facet, value), | |
172 | - params.merge(:facet => params[:facet].reject{ |k,v| k == id })] | |
173 | - end | |
104 | + def filter_selector(asset, filter, float = 'right') | |
105 | + klass = asset_class(asset) | |
106 | + if klass::SEARCH_FILTERS.count > 1 | |
107 | + options = options_for_select(klass::SEARCH_FILTERS.map {|f| [FILTER_TRANSLATION[f], f]}, filter) | |
108 | + url_params = url_for(params.merge(:filter => 'FILTER')) | |
109 | + onchange = "document.location.href = '#{url_params}'.replace('FILTER', this.value)" | |
110 | + select_field = select_tag(:filter, options, :onchange => onchange) | |
111 | + content_tag('div', | |
112 | + content_tag('strong', _('Filter')) + ': ' + select_field, | |
113 | + :class => "search-customize-options" | |
114 | + ) | |
174 | 115 | end |
175 | - | |
176 | - ret.map do |label, name, url| | |
177 | - content_tag('div', content_tag('span', label, :class => 'facet-selected-label') + | |
178 | - content_tag('span', name, :class => 'facet-selected-name') + | |
179 | - link_to('', url, :class => 'facet-selected-remove', :title => 'remove facet'), :class => 'facet-selected') | |
180 | - end.join | |
181 | - end | |
182 | - | |
183 | - def order_by(asset) | |
184 | - options = SortOptions[asset].map do |name, options| | |
185 | - next if options[:if] and ! instance_eval(&options[:if]) | |
186 | - [_(options[:label]), name.to_s] | |
187 | - end.compact | |
188 | - | |
189 | - content_tag('div', _('Sort results by ') + | |
190 | - select_tag(asset.to_s + '[order]', options_for_select(options, params[:order_by] || 'none'), | |
191 | - {:onchange => "window.location = jQuery.param.querystring(window.location.href, { 'order_by' : this.options[this.selectedIndex].value})"}), | |
192 | - :class => "search-ordering") | |
193 | - end | |
194 | - | |
195 | - def label_total_found(asset, total_found) | |
196 | - labels = { | |
197 | - :products => _("%s products offers found"), | |
198 | - :articles => _("%s articles found"), | |
199 | - :events => _("%s events found"), | |
200 | - :people => _("%s people found"), | |
201 | - :enterprises => _("%s enterprises found"), | |
202 | - :communities => _("%s communities found"), | |
203 | - } | |
204 | - content_tag('span', labels[asset] % total_found, | |
205 | - :class => "total-pages-found") if labels[asset] | |
206 | - end | |
207 | - | |
208 | - def asset_class(asset) | |
209 | - asset.to_s.singularize.camelize.constantize | |
210 | 116 | end |
211 | 117 | |
212 | - def asset_table(asset) | |
213 | - asset_class(asset).table_name | |
118 | + def filter_title(asset, filter) | |
119 | + { | |
120 | + 'articles_more_recent' => _('More recent contents from network'), | |
121 | + 'articles_more_popular' => _('More viewed contents from network'), | |
122 | + 'articles_more_comments' => _('Most commented contents from network'), | |
123 | + 'people_more_recent' => _('More recent people from network'), | |
124 | + 'people_more_active' => _('More active people from network'), | |
125 | + 'people_more_popular' => _('More popular people from network'), | |
126 | + 'communities_more_recent' => _('More recent communities from network'), | |
127 | + 'communities_more_active' => _('More active communities from network'), | |
128 | + 'communities_more_popular' => _('More popular communities from network'), | |
129 | + 'enterprises_more_recent' => _('More recent enterprises from network'), | |
130 | + 'enterprises_more_active' => _('More active enterprises from network'), | |
131 | + 'enterprises_more_popular' => _('More popular enterprises from network'), | |
132 | + 'products_more_recent' => _('Highlights'), | |
133 | + }[asset.to_s + '_' + filter].to_s | |
214 | 134 | end |
215 | 135 | |
216 | 136 | end | ... | ... |
app/helpers/tags_helper.rb
... | ... | @@ -29,10 +29,8 @@ module TagsHelper |
29 | 29 | # (pt_BR only). |
30 | 30 | def tag_cloud(tags, tagname_option, url, options = {}) |
31 | 31 | |
32 | - return content_tag('em', _('No tags yet.')) + | |
33 | - ' <a href="' + _('http://en.wikipedia.org/wiki/Tag_%28metadata%29') + | |
34 | - '" target="wptags"><span>(' + | |
35 | - _('What are tags?') + ')</span></a>' if tags.empty? | |
32 | + return content_tag('em', _('No tags yet.') + ' ') + | |
33 | + link_to(content_tag(:span, _('What are tags?')),_('http://en.wikipedia.org/wiki/Tag_%28metadata%29')) if tags.empty? | |
36 | 34 | |
37 | 35 | max_size = options[:max_size] || Cloud::MAX_SIZE |
38 | 36 | min_size = options[:min_size] || Cloud::MIN_SIZE |
... | ... | @@ -68,7 +66,7 @@ module TagsHelper |
68 | 66 | :title => n_( 'one item', '%d items', count ) % count |
69 | 67 | end |
70 | 68 | |
71 | - end.join("\n") | |
69 | + end.join("\n").html_safe | |
72 | 70 | end |
73 | 71 | |
74 | 72 | end | ... | ... |
app/models/approve_comment.rb
... | ... | @@ -43,7 +43,7 @@ class ApproveComment < Task |
43 | 43 | |
44 | 44 | def information |
45 | 45 | if article |
46 | - {:message => _('%{requestor} commented on the the article: %{linked_subject}.') % {:requestor => requestor_name} } | |
46 | + {:message => _('%{requestor} commented on the the article: %{linked_subject}.') % {:requestor => requestor_name, :linked_subject => linked_subject} } | |
47 | 47 | else |
48 | 48 | {:message => _("The article was removed.")} |
49 | 49 | end | ... | ... |
app/models/article.rb
... | ... | @@ -2,7 +2,28 @@ require 'hpricot' |
2 | 2 | |
3 | 3 | class Article < ActiveRecord::Base |
4 | 4 | |
5 | -include ActionController::UrlWriter | |
5 | + SEARCHABLE_FIELDS = { | |
6 | + :name => 10, | |
7 | + :abstract => 3, | |
8 | + :body => 2, | |
9 | + :slug => 1, | |
10 | + :filename => 1, | |
11 | + } | |
12 | + | |
13 | + SEARCH_FILTERS = %w[ | |
14 | + more_recent | |
15 | + more_popular | |
16 | + more_comments | |
17 | + ] | |
18 | + | |
19 | + SEARCH_DISPLAYS = %w[full] | |
20 | + | |
21 | + def self.default_search_display | |
22 | + 'full' | |
23 | + end | |
24 | + | |
25 | + #FIXME This is necessary because html is being generated on the model... | |
26 | + include ActionView::Helpers::TagHelper | |
6 | 27 | |
7 | 28 | # use for internationalizable human type names in search facets |
8 | 29 | # reimplement on subclasses |
... | ... | @@ -147,7 +168,6 @@ include ActionController::UrlWriter |
147 | 168 | else |
148 | 169 | ArticleCategorization.add_category_to_article(c, self) |
149 | 170 | self.categories(reload) |
150 | - self.solr_save | |
151 | 171 | end |
152 | 172 | end |
153 | 173 | |
... | ... | @@ -165,7 +185,6 @@ include ActionController::UrlWriter |
165 | 185 | ArticleCategorization.add_category_to_article(item, self) |
166 | 186 | end |
167 | 187 | self.categories(true) |
168 | - self.solr_save | |
169 | 188 | pending_categorizations.clear |
170 | 189 | end |
171 | 190 | |
... | ... | @@ -201,20 +220,12 @@ include ActionController::UrlWriter |
201 | 220 | named_scope :public, |
202 | 221 | :conditions => [ "advertise = ? AND published = ? AND profiles.visible = ? AND profiles.public_profile = ?", true, true, true, true ] |
203 | 222 | |
204 | - named_scope :more_recent, | |
205 | - :conditions => [ "advertise = ? AND published = ? AND profiles.visible = ? AND profiles.public_profile = ? AND | |
206 | - ((articles.type != ?) OR articles.type is NULL)", | |
207 | - true, true, true, true, 'RssFeed' | |
208 | - ], | |
209 | - :order => 'articles.published_at desc, articles.id desc' | |
210 | - | |
211 | 223 | # retrives the most commented articles, sorted by the comment count (largest |
212 | 224 | # first) |
213 | 225 | def self.most_commented(limit) |
214 | 226 | paginate(:order => 'comments_count DESC', :page => 1, :per_page => limit) |
215 | 227 | end |
216 | 228 | |
217 | - named_scope :more_popular, :order => 'hits DESC' | |
218 | 229 | named_scope :relevant_as_recent, :conditions => ["(articles.type != 'UploadedFile' and articles.type != 'RssFeed' and articles.type != 'Blog') OR articles.type is NULL"] |
219 | 230 | |
220 | 231 | def self.recent(limit = nil, extra_conditions = {}, pagination = true) |
... | ... | @@ -239,8 +250,13 @@ include ActionController::UrlWriter |
239 | 250 | # The implementation in this class just provides the +body+ attribute as the |
240 | 251 | # HTML. Other article types can override this method to provide customized |
241 | 252 | # views of themselves. |
253 | + # (To override short format representation, override the lead method) | |
242 | 254 | def to_html(options = {}) |
243 | - body || '' | |
255 | + if options[:format] == 'short' | |
256 | + display_short_format(self) | |
257 | + else | |
258 | + body || '' | |
259 | + end | |
244 | 260 | end |
245 | 261 | |
246 | 262 | include ApplicationHelper |
... | ... | @@ -429,8 +445,8 @@ include ActionController::UrlWriter |
429 | 445 | named_scope :images, :conditions => { :is_image => true } |
430 | 446 | named_scope :text_articles, :conditions => [ 'articles.type IN (?)', text_article_types ] |
431 | 447 | |
448 | + named_scope :more_popular, :order => 'hits DESC' | |
432 | 449 | named_scope :more_comments, :order => "comments_count DESC" |
433 | - named_scope :more_views, :order => "hits DESC" | |
434 | 450 | named_scope :more_recent, :order => "created_at DESC" |
435 | 451 | |
436 | 452 | def self.display_filter(user, profile) |
... | ... | @@ -596,7 +612,7 @@ include ActionController::UrlWriter |
596 | 612 | end |
597 | 613 | |
598 | 614 | def lead |
599 | - abstract.blank? ? first_paragraph : abstract | |
615 | + abstract.blank? ? first_paragraph.html_safe : abstract.html_safe | |
600 | 616 | end |
601 | 617 | |
602 | 618 | def short_lead |
... | ... | @@ -627,7 +643,7 @@ include ActionController::UrlWriter |
627 | 643 | |
628 | 644 | end |
629 | 645 | |
630 | - def more_views_label | |
646 | + def more_popular_label | |
631 | 647 | amount = self.hits |
632 | 648 | { |
633 | 649 | 0 => _('no views'), |
... | ... | @@ -655,98 +671,7 @@ include ActionController::UrlWriter |
655 | 671 | img.nil? ? '' : img.attributes['src'] |
656 | 672 | end |
657 | 673 | |
658 | - private | |
659 | - | |
660 | - # FIXME: workaround for development env. | |
661 | - # Subclasses aren't (re)loaded, and acts_as_solr | |
662 | - # depends on subclasses method to search | |
663 | - # see http://stackoverflow.com/questions/4138957/activerecordsubclassnotfound-error-when-using-sti-in-rails/4139245 | |
664 | - UploadedFile | |
665 | - TextArticle | |
666 | - TinyMceArticle | |
667 | - TextileArticle | |
668 | - Folder | |
669 | - EnterpriseHomepage | |
670 | - Gallery | |
671 | - Blog | |
672 | - Forum | |
673 | - Event | |
674 | - | |
675 | - def self.f_type_proc(klass) | |
676 | - klass.constantize.type_name | |
677 | - end | |
678 | - | |
679 | - def self.f_profile_type_proc(klass) | |
680 | - klass.constantize.type_name | |
681 | - end | |
682 | - | |
683 | - def f_type | |
684 | - #join common types | |
685 | - case self.class.name | |
686 | - when 'TinyMceArticle', 'TextileArticle' | |
687 | - TextArticle.name | |
688 | - else | |
689 | - self.class.name | |
690 | - end | |
691 | - end | |
692 | - | |
693 | - def f_profile_type | |
694 | - self.profile.class.name | |
695 | - end | |
696 | - | |
697 | - def f_published_at | |
698 | - self.published_at | |
699 | - end | |
700 | - | |
701 | - def f_category | |
702 | - self.categories.collect(&:name) | |
703 | - end | |
704 | - | |
705 | 674 | delegate :region, :region_id, :environment, :environment_id, :to => :profile, :allow_nil => true |
706 | - def name_sortable # give a different name for solr | |
707 | - name | |
708 | - end | |
709 | - | |
710 | - def public | |
711 | - self.public? | |
712 | - end | |
713 | - | |
714 | - def category_filter | |
715 | - categories_including_virtual_ids | |
716 | - end | |
717 | - | |
718 | - public | |
719 | - | |
720 | - acts_as_faceted :fields => { | |
721 | - :f_type => {:label => _('Type'), :proc => proc{|klass| f_type_proc(klass)}}, | |
722 | - :f_published_at => {:type => :date, :label => _('Published date'), :queries => {'[* TO NOW-1YEARS/DAY]' => _("Older than one year"), | |
723 | - '[NOW-1YEARS TO NOW/DAY]' => _("In the last year"), '[NOW-1MONTHS TO NOW/DAY]' => _("In the last month"), '[NOW-7DAYS TO NOW/DAY]' => _("In the last week"), '[NOW-1DAYS TO NOW/DAY]' => _("In the last day")}, | |
724 | - :queries_order => ['[NOW-1DAYS TO NOW/DAY]', '[NOW-7DAYS TO NOW/DAY]', '[NOW-1MONTHS TO NOW/DAY]', '[NOW-1YEARS TO NOW/DAY]', '[* TO NOW-1YEARS/DAY]']}, | |
725 | - :f_profile_type => {:label => _('Profile'), :proc => proc{|klass| f_profile_type_proc(klass)}}, | |
726 | - :f_category => {:label => _('Categories')}, | |
727 | - }, :category_query => proc { |c| "category_filter:\"#{c.id}\"" }, | |
728 | - :order => [:f_type, :f_published_at, :f_profile_type, :f_category] | |
729 | - | |
730 | - acts_as_searchable :fields => facets_fields_for_solr + [ | |
731 | - # searched fields | |
732 | - {:name => {:type => :text, :boost => 2.0}}, | |
733 | - {:slug => :text}, {:body => :text}, | |
734 | - {:abstract => :text}, {:filename => :text}, | |
735 | - # filtered fields | |
736 | - {:public => :boolean}, {:environment_id => :integer}, | |
737 | - {:profile_id => :integer}, :language, | |
738 | - {:category_filter => :integer}, | |
739 | - # ordered/query-boosted fields | |
740 | - {:name_sortable => :string}, :last_changed_by_id, :published_at, :is_image, | |
741 | - :updated_at, :created_at, | |
742 | - ], :include => [ | |
743 | - {:profile => {:fields => [:name, :identifier, :address, :nickname, :region_id, :lat, :lng]}}, | |
744 | - {:comments => {:fields => [:title, :body, :author_name, :author_email]}}, | |
745 | - {:categories => {:fields => [:name, :path, :slug, :lat, :lng, :acronym, :abbreviation]}}, | |
746 | - ], :facets => facets_option_for_solr, | |
747 | - :boost => proc { |a| 10 if a.profile && a.profile.enabled }, | |
748 | - :if => proc{ |a| ! ['RssFeed'].include?(a.class.name) } | |
749 | - handle_asynchronously :solr_save | |
750 | 675 | |
751 | 676 | private |
752 | 677 | ... | ... |
app/models/article_block.rb
... | ... | @@ -12,7 +12,11 @@ class ArticleBlock < Block |
12 | 12 | block = self |
13 | 13 | lambda do |
14 | 14 | block_title(block.title) + |
15 | - (block.article ? article_to_html(block.article, :gallery_view => false) : _('Article not selected yet.')) | |
15 | + (block.article ? article_to_html(block.article, | |
16 | + :gallery_view => false, | |
17 | + :inside_block => block, # For Blogs and folders | |
18 | + :format => block.visualization_format # For Articles and contents | |
19 | + ).html_safe : _('Article not selected yet.')) | |
16 | 20 | end |
17 | 21 | end |
18 | 22 | |
... | ... | @@ -49,4 +53,14 @@ class ArticleBlock < Block |
49 | 53 | self.box.owner.kind_of?(Environment) ? self.box.owner.portal_community.articles : self.box.owner.articles |
50 | 54 | end |
51 | 55 | |
56 | + def posts_per_page | |
57 | + self.settings[:posts_per_page] or 1 | |
58 | + end | |
59 | + | |
60 | + def posts_per_page= value | |
61 | + value = value.to_i | |
62 | + self.settings[:posts_per_page] = value if value > 0 | |
63 | + end | |
64 | + | |
65 | + settings_items :visualization_format, :type => :string, :default => 'short' | |
52 | 66 | end | ... | ... |
app/models/blog.rb
... | ... | @@ -24,8 +24,9 @@ class Blog < Folder |
24 | 24 | # FIXME isn't this too much including just to be able to generate some HTML? |
25 | 25 | include ActionView::Helpers::TagHelper |
26 | 26 | def to_html(options = {}) |
27 | + me = self | |
27 | 28 | lambda do |
28 | - render :file => 'content_viewer/blog_page' | |
29 | + render :file => 'content_viewer/blog_page', :locals => { :blog=>me, :inside_block=>options[:inside_block] } | |
29 | 30 | end |
30 | 31 | end |
31 | 32 | ... | ... |
app/models/category.rb
1 | 1 | class Category < ActiveRecord::Base |
2 | 2 | |
3 | + SEARCHABLE_FIELDS = { | |
4 | + :name => 10, | |
5 | + :acronym => 5, | |
6 | + :abbreviation => 5, | |
7 | + :slug => 1, | |
8 | + } | |
9 | + | |
3 | 10 | validates_exclusion_of :slug, :in => [ 'index' ], :message => N_('%{fn} cannot be like that.').fix_i18n |
4 | 11 | validates_presence_of :name, :environment_id |
5 | 12 | validates_uniqueness_of :slug,:scope => [ :environment_id, :parent_id ], :message => N_('%{fn} is already being used by another category.').fix_i18n |
... | ... | @@ -100,23 +107,4 @@ class Category < ActiveRecord::Base |
100 | 107 | self.children.find(:all, :conditions => {:display_in_menu => true}).empty? |
101 | 108 | end |
102 | 109 | |
103 | - private | |
104 | - def name_sortable # give a different name for solr | |
105 | - name | |
106 | - end | |
107 | - public | |
108 | - | |
109 | - acts_as_searchable :fields => [ | |
110 | - # searched fields | |
111 | - {:name => {:type => :text, :boost => 2.0}}, | |
112 | - {:path => :text}, {:slug => :text}, | |
113 | - {:abbreviation => :text}, {:acronym => :text}, | |
114 | - # filtered fields | |
115 | - :parent_id, | |
116 | - # ordered/query-boosted fields | |
117 | - {:name_sortable => :string}, | |
118 | - ] | |
119 | - after_save_reindex [:articles, :profiles], :with => :delayed_job | |
120 | - handle_asynchronously :solr_save | |
121 | - | |
122 | 110 | end | ... | ... |
app/models/certifier.rb
1 | 1 | class Certifier < ActiveRecord::Base |
2 | 2 | |
3 | + SEARCHABLE_FIELDS = { | |
4 | + :name => 10, | |
5 | + :description => 3, | |
6 | + :link => 1, | |
7 | + } | |
8 | + | |
3 | 9 | belongs_to :environment |
4 | 10 | |
5 | 11 | has_many :qualifier_certifiers, :dependent => :destroy |
... | ... | @@ -24,6 +30,4 @@ class Certifier < ActiveRecord::Base |
24 | 30 | self.name.downcase.transliterate <=> b.name.downcase.transliterate |
25 | 31 | end |
26 | 32 | |
27 | - after_save_reindex [:products], :with => :delayed_job | |
28 | - | |
29 | 33 | end | ... | ... |
app/models/comment.rb
1 | 1 | class Comment < ActiveRecord::Base |
2 | 2 | |
3 | + SEARCHABLE_FIELDS = { | |
4 | + :title => 10, | |
5 | + :name => 4, | |
6 | + :body => 2, | |
7 | + } | |
8 | + | |
3 | 9 | validates_presence_of :body |
4 | 10 | |
5 | 11 | belongs_to :source, :counter_cache => true, :polymorphic => true |
... | ... | @@ -85,12 +91,6 @@ class Comment < ActiveRecord::Base |
85 | 91 | self.article.profile.notification_emails - [self.author_email || self.email] |
86 | 92 | end |
87 | 93 | |
88 | - after_save :notify_article | |
89 | - after_destroy :notify_article | |
90 | - def notify_article | |
91 | - article.comments_updated if article.kind_of?(Article) | |
92 | - end | |
93 | - | |
94 | 94 | after_create :new_follower |
95 | 95 | def new_follower |
96 | 96 | if source.kind_of?(Article) | ... | ... |
app/models/enterprise.rb
... | ... | @@ -2,6 +2,8 @@ |
2 | 2 | # only enterprises can offer products and services. |
3 | 3 | class Enterprise < Organization |
4 | 4 | |
5 | + SEARCH_DISPLAYS += %w[map full] | |
6 | + | |
5 | 7 | def self.type_name |
6 | 8 | _('Enterprise') |
7 | 9 | end |
... | ... | @@ -14,8 +16,6 @@ class Enterprise < Organization |
14 | 16 | |
15 | 17 | has_and_belongs_to_many :fans, :class_name => 'Person', :join_table => 'favorite_enteprises_people' |
16 | 18 | |
17 | - after_save_reindex [:products], :with => :delayed_job | |
18 | - extra_data_for_index :product_categories | |
19 | 19 | def product_categories |
20 | 20 | products.includes(:product_category).map{|p| p.category_full_name}.compact |
21 | 21 | end |
... | ... | @@ -182,7 +182,15 @@ class Enterprise < Organization |
182 | 182 | end |
183 | 183 | |
184 | 184 | def activities |
185 | - Scrap.find_by_sql("SELECT id, updated_at, 'Scrap' AS klass FROM scraps WHERE scraps.receiver_id = #{self.id} AND scraps.scrap_id IS NULL UNION SELECT id, updated_at, 'ActionTracker::Record' AS klass FROM action_tracker WHERE action_tracker.target_id = #{self.id} UNION SELECT action_tracker.id, action_tracker.updated_at, 'ActionTracker::Record' AS klass FROM action_tracker INNER JOIN articles ON action_tracker.target_id = articles.id WHERE articles.profile_id = #{self.id} AND action_tracker.target_type = 'Article' ORDER BY action_tracker.updated_at DESC") | |
185 | + Scrap.find_by_sql("SELECT id, updated_at, 'Scrap' AS klass FROM scraps WHERE scraps.receiver_id = #{self.id} AND scraps.scrap_id IS NULL UNION SELECT id, updated_at, 'ActionTracker::Record' AS klass FROM action_tracker WHERE action_tracker.target_id = #{self.id} UNION SELECT action_tracker.id, action_tracker.updated_at, 'ActionTracker::Record' AS klass FROM action_tracker INNER JOIN articles ON action_tracker.target_id = articles.id WHERE articles.profile_id = #{self.id} AND action_tracker.target_type = 'Article' ORDER BY updated_at DESC") | |
186 | + end | |
187 | + | |
188 | + def catalog_url | |
189 | + { :profile => identifier, :controller => 'catalog'} | |
190 | + end | |
191 | + | |
192 | + def more_recent_label | |
193 | + '' | |
186 | 194 | end |
187 | 195 | |
188 | 196 | end | ... | ... |
app/models/environment.rb
... | ... | @@ -268,8 +268,6 @@ class Environment < ActiveRecord::Base |
268 | 268 | |
269 | 269 | settings_items :search_hints, :type => Hash, :default => {} |
270 | 270 | |
271 | - settings_items :top_level_category_as_facet_ids, :type => Array, :default => [] | |
272 | - | |
273 | 271 | def news_amount_by_folder=(amount) |
274 | 272 | settings[:news_amount_by_folder] = amount.to_i |
275 | 273 | end |
... | ... | @@ -618,12 +616,10 @@ class Environment < ActiveRecord::Base |
618 | 616 | end |
619 | 617 | |
620 | 618 | def top_url |
621 | - protocol = 'http' | |
622 | - result = "#{protocol}://#{default_hostname}" | |
623 | - if Noosfero.url_options.has_key?(:port) | |
624 | - result << ':' << Noosfero.url_options[:port].to_s | |
625 | - end | |
626 | - result | |
619 | + url = 'http://' | |
620 | + url << (Noosfero.url_options.key?(:host) ? Noosfero.url_options[:host] : default_hostname) | |
621 | + url << ':' << Noosfero.url_options[:port].to_s if Noosfero.url_options.key?(:port) | |
622 | + url | |
627 | 623 | end |
628 | 624 | |
629 | 625 | def to_s | ... | ... |
app/models/event.rb
... | ... | @@ -14,7 +14,6 @@ class Event < Article |
14 | 14 | maybe_add_http(self.setting[:link]) |
15 | 15 | end |
16 | 16 | |
17 | - xss_terminate :only => [ :link ], :on => 'validation' | |
18 | 17 | xss_terminate :only => [ :body, :link, :address ], :with => 'white_list', :on => 'validation' |
19 | 18 | |
20 | 19 | def initialize(*args) |
... | ... | @@ -104,18 +103,30 @@ class Event < Article |
104 | 103 | } |
105 | 104 | } |
106 | 105 | |
106 | + # TODO: some good soul, please clean this ugly hack: | |
107 | 107 | if self.body |
108 | 108 | html.div('_____XXXX_DESCRIPTION_GOES_HERE_XXXX_____', :class => 'event-description') |
109 | 109 | end |
110 | 110 | } |
111 | 111 | |
112 | 112 | if self.body |
113 | - result.sub!('_____XXXX_DESCRIPTION_GOES_HERE_XXXX_____', self.body) | |
113 | + if options[:format] == 'short' | |
114 | + result.sub!('_____XXXX_DESCRIPTION_GOES_HERE_XXXX_____', display_short_format(self)) | |
115 | + else | |
116 | + result.sub!('_____XXXX_DESCRIPTION_GOES_HERE_XXXX_____', self.body) | |
117 | + end | |
114 | 118 | end |
115 | 119 | |
116 | 120 | result |
117 | 121 | end |
118 | 122 | |
123 | + def lead | |
124 | + content_tag('div', | |
125 | + show_period(start_date, end_date), | |
126 | + :class => 'event-dates' | |
127 | + ) + super | |
128 | + end | |
129 | + | |
119 | 130 | def event? |
120 | 131 | true |
121 | 132 | end | ... | ... |
app/models/external_feed.rb
... | ... | @@ -11,6 +11,15 @@ class ExternalFeed < ActiveRecord::Base |
11 | 11 | } |
12 | 12 | |
13 | 13 | def add_item(title, link, date, content) |
14 | + doc = Hpricot(content) | |
15 | + doc.search('*').each do |p| | |
16 | + if p.instance_of? Hpricot::Elem | |
17 | + p.remove_attribute 'style' | |
18 | + p.remove_attribute 'class' | |
19 | + end | |
20 | + end | |
21 | + content = doc.to_s | |
22 | + | |
14 | 23 | article = TinyMceArticle.new(:name => title, :profile => blog.profile, :body => content, :published_at => date, :source => link, :profile => blog.profile, :parent => blog) |
15 | 24 | unless blog.children.exists?(:slug => article.slug) |
16 | 25 | article.save! | ... | ... |
app/models/feed_reader_block.rb
... | ... | @@ -47,11 +47,11 @@ class FeedReaderBlock < Block |
47 | 47 | |
48 | 48 | def formatted_feed_content |
49 | 49 | if error_message.blank? |
50 | - "<ul>\n" + | |
51 | - self.feed_items[0..(limit-1)].map{ |item| "<li><a href='#{item[:link]}'>#{item[:title]}</a></li>" }.join("\n") + | |
52 | - "</ul>" | |
50 | + "<ul>\n".html_safe + | |
51 | + self.feed_items[0..(limit-1)].map{ |item| "<li><a href='#{item[:link]}'>#{item[:title]}</a></li>" }.join("\n").html_safe + | |
52 | + "</ul>".html_safe | |
53 | 53 | else |
54 | - '<p>' + error_message + '</p>' | |
54 | + "<p>#{error_message}</p>".html_safe | |
55 | 55 | end |
56 | 56 | end |
57 | 57 | ... | ... |
app/models/license.rb
app/models/link_list_block.rb
... | ... | @@ -80,7 +80,7 @@ class LinkListBlock < Block |
80 | 80 | |
81 | 81 | def icons_options |
82 | 82 | ICONS.map do |i| |
83 | - "<span title=\"#{i[1]}\" class=\"icon-#{i[0]}\" onclick=\"changeIcon(this, '#{i[0]}')\"></span>" | |
83 | + "<span title=\"#{i[1]}\" class=\"icon-#{i[0]}\" onclick=\"changeIcon(this, '#{i[0]}')\"></span>".html_safe | |
84 | 84 | end |
85 | 85 | end |
86 | 86 | ... | ... |
app/models/national_region.rb
app/models/organization.rb
app/models/organization_mailing.rb
... | ... | @@ -5,7 +5,7 @@ class OrganizationMailing < Mailing |
5 | 5 | end |
6 | 6 | |
7 | 7 | def recipients(offset=0, limit=100) |
8 | - source.members.all(:order => self.id, :offset => offset, :limit => limit, :joins => "LEFT OUTER JOIN mailing_sents m ON (m.mailing_id = #{id} AND m.person_id = profiles.id)", :conditions => { "m.person_id" => nil }) | |
8 | + source.members.all(:order => :id, :offset => offset, :limit => limit, :joins => "LEFT OUTER JOIN mailing_sents m ON (m.mailing_id = #{id} AND m.person_id = profiles.id)", :conditions => { "m.person_id" => nil }) | |
9 | 9 | end |
10 | 10 | |
11 | 11 | def each_recipient | ... | ... |
app/models/person.rb
app/models/product.rb
1 | 1 | class Product < ActiveRecord::Base |
2 | 2 | |
3 | + SEARCHABLE_FIELDS = { | |
4 | + :name => 10, | |
5 | + :description => 1, | |
6 | + } | |
7 | + | |
8 | + SEARCH_FILTERS = %w[ | |
9 | + more_recent | |
10 | + ] | |
11 | + | |
12 | + SEARCH_DISPLAYS = %w[map full] | |
13 | + | |
14 | + def self.default_search_display | |
15 | + 'full' | |
16 | + end | |
17 | + | |
3 | 18 | belongs_to :enterprise |
4 | 19 | has_one :region, :through => :enterprise |
5 | 20 | validates_presence_of :enterprise |
... | ... | @@ -173,7 +188,7 @@ class Product < ActiveRecord::Base |
173 | 188 | |
174 | 189 | def price_described? |
175 | 190 | return false if price.blank? or price == 0 |
176 | - (price - total_production_cost).zero? | |
191 | + (price - total_production_cost.to_f).zero? | |
177 | 192 | end |
178 | 193 | |
179 | 194 | def update_price_details(price_details) |
... | ... | @@ -215,89 +230,6 @@ class Product < ActiveRecord::Base |
215 | 230 | end |
216 | 231 | end |
217 | 232 | |
218 | - private | |
219 | - def f_category | |
220 | - self.product_category.name | |
221 | - end | |
222 | - def f_region | |
223 | - self.enterprise.region.id if self.enterprise.region | |
224 | - end | |
225 | - def self.f_region_proc(id) | |
226 | - c = Region.find(id) | |
227 | - s = c.parent | |
228 | - if c and c.kind_of?(City) and s and s.kind_of?(State) and s.acronym | |
229 | - [c.name, ', ' + s.acronym] | |
230 | - else | |
231 | - c.name | |
232 | - end | |
233 | - end | |
234 | - def self.f_qualifier_proc(ids) | |
235 | - array = ids.split | |
236 | - qualifier = Qualifier.find_by_id array[0] | |
237 | - certifier = Certifier.find_by_id array[1] | |
238 | - certifier ? [qualifier.name, _(' cert. ') + certifier.name] : qualifier.name | |
239 | - end | |
240 | - def f_qualifier | |
241 | - product_qualifiers.map do |pq| | |
242 | - "#{pq.qualifier_id} #{pq.certifier_id}" | |
243 | - end | |
244 | - end | |
245 | - | |
246 | - alias_method :name_sortable, :name | |
247 | 233 | delegate :enabled, :region, :region_id, :environment, :environment_id, :to => :enterprise |
248 | - def name_sortable # give a different name for solr | |
249 | - name | |
250 | - end | |
251 | - def public | |
252 | - self.public? | |
253 | - end | |
254 | - def price_sortable | |
255 | - (price.nil? or price.zero?) ? nil : price | |
256 | - end | |
257 | - def category_filter | |
258 | - enterprise.categories_including_virtual_ids << product_category_id | |
259 | - end | |
260 | - public | |
261 | - | |
262 | - acts_as_faceted :fields => { | |
263 | - :f_category => {:label => _('Related products')}, | |
264 | - :f_region => {:label => _('City'), :proc => proc { |id| f_region_proc(id) }}, | |
265 | - :f_qualifier => {:label => _('Qualifiers'), :proc => proc { |id| f_qualifier_proc(id) }}, | |
266 | - }, :category_query => proc { |c| "category_filter:#{c.id}" }, | |
267 | - :order => [:f_category, :f_region, :f_qualifier] | |
268 | - | |
269 | - Boosts = [ | |
270 | - [:image, 0.55, proc{ |p| p.image ? 1 : 0}], | |
271 | - [:qualifiers, 0.45, proc{ |p| p.product_qualifiers.count > 0 ? 1 : 0}], | |
272 | - [:open_price, 0.45, proc{ |p| p.price_described? ? 1 : 0}], | |
273 | - [:solidarity, 0.45, proc{ |p| p.percentage_from_solidarity_economy[0].to_f/100 }], | |
274 | - [:available, 0.35, proc{ |p| p.available ? 1 : 0}], | |
275 | - [:price, 0.35, proc{ |p| (!p.price.nil? and p.price > 0) ? 1 : 0}], | |
276 | - [:new_product, 0.35, proc{ |p| (p.updated_at.to_i - p.created_at.to_i) < 24*3600 ? 1 : 0}], | |
277 | - [:description, 0.3, proc{ |p| !p.description.blank? ? 1 : 0}], | |
278 | - [:enabled, 0.2, proc{ |p| p.enterprise.enabled ? 1 : 0}], | |
279 | - ] | |
280 | - | |
281 | - acts_as_searchable :fields => facets_fields_for_solr + [ | |
282 | - # searched fields | |
283 | - {:name => {:type => :text, :boost => 2.0}}, | |
284 | - {:description => :text}, {:category_full_name => :text}, | |
285 | - # filtered fields | |
286 | - {:public => :boolean}, {:environment_id => :integer}, | |
287 | - {:enabled => :boolean}, {:category_filter => :integer}, | |
288 | - # ordered/query-boosted fields | |
289 | - {:price_sortable => :decimal}, {:name_sortable => :string}, | |
290 | - {:lat => :float}, {:lng => :float}, | |
291 | - :updated_at, :created_at, | |
292 | - ], :include => [ | |
293 | - {:product_category => {:fields => [:name, :path, :slug, :lat, :lng, :acronym, :abbreviation]}}, | |
294 | - {:region => {:fields => [:name, :path, :slug, :lat, :lng]}}, | |
295 | - {:enterprise => {:fields => [:name, :identifier, :address, :nickname, :lat, :lng]}}, | |
296 | - {:qualifiers => {:fields => [:name]}}, | |
297 | - {:certifiers => {:fields => [:name]}}, | |
298 | - ], :facets => facets_option_for_solr, | |
299 | - :boost => proc{ |p| boost = 1; Boosts.each{ |b| boost = boost * (1 - ((1 - b[2].call(p)) * b[1])) }; boost} | |
300 | - handle_asynchronously :solr_save | |
301 | - after_save_reindex [:enterprise], :with => :delayed_job | |
302 | 234 | |
303 | 235 | end | ... | ... |
app/models/product_category.rb
app/models/profile.rb
... | ... | @@ -3,10 +3,20 @@ |
3 | 3 | # which by default is the one returned by Environment:default. |
4 | 4 | class Profile < ActiveRecord::Base |
5 | 5 | |
6 | - # use for internationalizable human type names in search facets | |
7 | - # reimplement on subclasses | |
8 | - def self.type_name | |
9 | - _('Profile') | |
6 | + SEARCHABLE_FIELDS = { | |
7 | + :name => 10, | |
8 | + :identifier => 5, | |
9 | + :nickname => 2, | |
10 | + } | |
11 | + | |
12 | + SEARCH_FILTERS = %w[ | |
13 | + more_recent | |
14 | + ] | |
15 | + | |
16 | + SEARCH_DISPLAYS = %w[compact] | |
17 | + | |
18 | + def self.default_search_display | |
19 | + 'compact' | |
10 | 20 | end |
11 | 21 | |
12 | 22 | module Roles |
... | ... | @@ -68,7 +78,7 @@ class Profile < ActiveRecord::Base |
68 | 78 | #FIXME: these will work only if the subclass is already loaded |
69 | 79 | named_scope :enterprises, lambda { {:conditions => (Enterprise.send(:subclasses).map(&:name) << 'Enterprise').map { |klass| "profiles.type = '#{klass}'"}.join(" OR ")} } |
70 | 80 | named_scope :communities, lambda { {:conditions => (Community.send(:subclasses).map(&:name) << 'Community').map { |klass| "profiles.type = '#{klass}'"}.join(" OR ")} } |
71 | - named_scope :templates, :conditions => {:is_template => true} | |
81 | + named_scope :templates, lambda { |environment| { :conditions => {:is_template => true, :environment_id => environment.id} } } | |
72 | 82 | |
73 | 83 | def members |
74 | 84 | scopes = plugins.dispatch_scopes(:organization_members, self) |
... | ... | @@ -127,18 +137,6 @@ class Profile < ActiveRecord::Base |
127 | 137 | scrap.nil? ? Scrap.all_scraps(self) : Scrap.all_scraps(self).find(scrap) |
128 | 138 | end |
129 | 139 | |
130 | - class_inheritable_accessor :extra_index_methods | |
131 | - self.extra_index_methods = [] | |
132 | - | |
133 | - def extra_data_for_index | |
134 | - self.class.extra_index_methods.map { |meth| meth.to_proc.call(self) }.flatten | |
135 | - end | |
136 | - | |
137 | - def self.extra_data_for_index(sym = nil, &block) | |
138 | - self.extra_index_methods.push(sym) if sym | |
139 | - self.extra_index_methods.push(block) if block_given? | |
140 | - end | |
141 | - | |
142 | 140 | acts_as_having_settings :field => :data |
143 | 141 | |
144 | 142 | def settings |
... | ... | @@ -211,7 +209,7 @@ class Profile < ActiveRecord::Base |
211 | 209 | has_many :profile_categorizations_including_virtual, :class_name => 'ProfileCategorization' |
212 | 210 | has_many :categories_including_virtual, :through => :profile_categorizations_including_virtual, :source => :category |
213 | 211 | |
214 | - has_many :abuse_complaints, :foreign_key => 'requestor_id' | |
212 | + has_many :abuse_complaints, :foreign_key => 'requestor_id', :dependent => :destroy | |
215 | 213 | |
216 | 214 | def top_level_categorization |
217 | 215 | ret = {} |
... | ... | @@ -262,7 +260,6 @@ class Profile < ActiveRecord::Base |
262 | 260 | else |
263 | 261 | ProfileCategorization.add_category_to_profile(c, self) |
264 | 262 | self.categories(true) |
265 | - self.solr_save | |
266 | 263 | end |
267 | 264 | self.categories(reload) |
268 | 265 | end |
... | ... | @@ -894,86 +891,6 @@ private :generate_url, :url_options |
894 | 891 | self.active_fields |
895 | 892 | end |
896 | 893 | |
897 | - private | |
898 | - def self.f_categories_label_proc(environment) | |
899 | - ids = environment.top_level_category_as_facet_ids | |
900 | - r = Category.find(ids) | |
901 | - map = {} | |
902 | - ids.map{ |id| map[id.to_s] = r.detect{|c| c.id == id}.name } | |
903 | - map | |
904 | - end | |
905 | - def self.f_categories_proc(facet, id) | |
906 | - id = id.to_i | |
907 | - return if id.zero? | |
908 | - c = Category.find(id) | |
909 | - c.name if c.top_ancestor.id == facet[:label_id].to_i or facet[:label_id] == 0 | |
910 | - end | |
911 | - def f_categories | |
912 | - category_ids - [region_id] | |
913 | - end | |
914 | - | |
915 | - def f_region | |
916 | - self.region_id | |
917 | - end | |
918 | - def self.f_region_proc(id) | |
919 | - c = Region.find(id) | |
920 | - s = c.parent | |
921 | - if c and c.kind_of?(City) and s and s.kind_of?(State) and s.acronym | |
922 | - [c.name, ', ' + s.acronym] | |
923 | - else | |
924 | - c.name | |
925 | - end | |
926 | - end | |
927 | - | |
928 | - def self.f_enabled_proc(enabled) | |
929 | - enabled = enabled == "true" ? true : false | |
930 | - enabled ? s_('facets|Enabled') : s_('facets|Not enabled') | |
931 | - end | |
932 | - def f_enabled | |
933 | - self.enabled | |
934 | - end | |
935 | - | |
936 | - def name_sortable # give a different name for solr | |
937 | - name | |
938 | - end | |
939 | - def public | |
940 | - self.public? | |
941 | - end | |
942 | - def category_filter | |
943 | - categories_including_virtual_ids | |
944 | - end | |
945 | - public | |
946 | - | |
947 | - acts_as_faceted :fields => { | |
948 | - :f_enabled => {:label => _('Situation'), :type_if => proc { |klass| klass.kind_of?(Enterprise) }, | |
949 | - :proc => proc { |id| f_enabled_proc(id) }}, | |
950 | - :f_region => {:label => _('City'), :proc => proc { |id| f_region_proc(id) }}, | |
951 | - :f_categories => {:multi => true, :proc => proc {|facet, id| f_categories_proc(facet, id)}, | |
952 | - :label => proc { |env| f_categories_label_proc(env) }, :label_abbrev => proc{ |env| f_categories_label_abbrev_proc(env) }}, | |
953 | - }, :category_query => proc { |c| "category_filter:#{c.id}" }, | |
954 | - :order => [:f_region, :f_categories, :f_enabled] | |
955 | - | |
956 | - acts_as_searchable :fields => facets_fields_for_solr + [:extra_data_for_index, | |
957 | - # searched fields | |
958 | - {:name => {:type => :text, :boost => 2.0}}, | |
959 | - {:identifier => :text}, {:nickname => :text}, | |
960 | - # filtered fields | |
961 | - {:public => :boolean}, {:environment_id => :integer}, | |
962 | - {:category_filter => :integer}, | |
963 | - # ordered/query-boosted fields | |
964 | - {:name_sortable => :string}, {:user_id => :integer}, | |
965 | - :enabled, :active, :validated, :public_profile, | |
966 | - {:lat => :float}, {:lng => :float}, | |
967 | - :updated_at, :created_at, | |
968 | - ], | |
969 | - :include => [ | |
970 | - {:region => {:fields => [:name, :path, :slug, :lat, :lng]}}, | |
971 | - {:categories => {:fields => [:name, :path, :slug, :lat, :lng, :acronym, :abbreviation]}}, | |
972 | - ], :facets => facets_option_for_solr, | |
973 | - :boost => proc{ |p| 10 if p.enabled } | |
974 | - after_save_reindex [:articles], :with => :delayed_job | |
975 | - handle_asynchronously :solr_save | |
976 | - | |
977 | 894 | def control_panel_settings_button |
978 | 895 | {:title => _('Profile Info and settings'), :icon => 'edit-profile'} |
979 | 896 | end | ... | ... |
app/models/profile_list_block.rb
... | ... | @@ -49,13 +49,12 @@ class ProfileListBlock < Block |
49 | 49 | send(:profile_image_link, item, :minor ) |
50 | 50 | }.join("\n ") |
51 | 51 | if list.empty? |
52 | - list = '<div class="common-profile-list-block-none">'+ _('None') +'</div>' | |
52 | + list = content_tag 'div', _('None'), :class => 'common-profile-list-block-none' | |
53 | 53 | else |
54 | 54 | list = content_tag 'ul', nl +' '+ list + nl |
55 | 55 | end |
56 | 56 | block_title(title) + nl + |
57 | - '<div class="common-profile-list-block">' + | |
58 | - nl + list + nl + '<br style="clear:both" /></div>' | |
57 | + content_tag('div', nl + list + nl + content_tag('br', '', :style => 'clear:both')) | |
59 | 58 | end |
60 | 59 | end |
61 | 60 | ... | ... |
app/models/qualifier.rb
1 | 1 | class Qualifier < ActiveRecord::Base |
2 | 2 | |
3 | + SEARCHABLE_FIELDS = { | |
4 | + :name => 1, | |
5 | + } | |
6 | + | |
3 | 7 | belongs_to :environment |
4 | 8 | |
5 | 9 | has_many :qualifier_certifiers, :dependent => :destroy |
... | ... | @@ -15,6 +19,4 @@ class Qualifier < ActiveRecord::Base |
15 | 19 | self.name.downcase.transliterate <=> b.name.downcase.transliterate |
16 | 20 | end |
17 | 21 | |
18 | - after_save_reindex [:products], :with => :delayed_job | |
19 | - | |
20 | 22 | end | ... | ... |
app/models/raw_html_block.rb
app/models/region.rb
... | ... | @@ -4,12 +4,6 @@ class Region < Category |
4 | 4 | |
5 | 5 | require_dependency 'enterprise' # enterprises can also be validators |
6 | 6 | |
7 | - # searches for organizations that could become validators for this region. | |
8 | - # <tt>search</tt> is passed as is to find_by_contents on Organization. | |
9 | - def search_possible_validators(search) | |
10 | - Organization.find_by_contents(search)[:results].docs.reject {|item| self.validator_ids.include?(item.id) } | |
11 | - end | |
12 | - | |
13 | 7 | def has_validator? |
14 | 8 | validators.count > 0 |
15 | 9 | end | ... | ... |
app/models/scrap.rb
app/models/spammer_logger.rb
... | ... | @@ -5,10 +5,10 @@ class SpammerLogger < Logger |
5 | 5 | def self.log(spammer_ip, object=nil) |
6 | 6 | if object |
7 | 7 | if object.kind_of?(Comment) |
8 | - @logger << "[#{Time.now.strftime("%F %T %z")}] Comment-id: #{object.id} IP: #{spammer_ip}\n" | |
8 | + @logger << "[#{Time.now.strftime('%F %T %z')}] Comment-id: #{object.id} IP: #{spammer_ip}\n" | |
9 | 9 | end |
10 | 10 | else |
11 | - @logger << "[#{Time.now.strftime("%F %T %z")}] IP: #{spammer_ip}\n" | |
11 | + @logger << "[#{Time.now.strftime('%F %T %z')}] IP: #{spammer_ip}\n" | |
12 | 12 | end |
13 | 13 | end |
14 | 14 | ... | ... |
app/models/tags_block.rb
... | ... | @@ -20,7 +20,8 @@ class TagsBlock < Block |
20 | 20 | end |
21 | 21 | |
22 | 22 | def content(args={}) |
23 | - tags = owner.article_tags | |
23 | + is_env = owner.class == Environment | |
24 | + tags = is_env ? owner.tag_counts : owner.article_tags | |
24 | 25 | return '' if tags.empty? |
25 | 26 | |
26 | 27 | if limit |
... | ... | @@ -29,18 +30,28 @@ class TagsBlock < Block |
29 | 30 | tags_tmp.map{ |k,v| tags[k] = v } |
30 | 31 | end |
31 | 32 | |
33 | + url = is_env ? {:host=>owner.default_hostname, :controller=>'search', :action => 'tag'} : | |
34 | + owner.public_profile_url.merge(:controller => 'profile', :action => 'tags') | |
35 | + tagname_option = is_env ? :tag : :id | |
36 | + | |
32 | 37 | block_title(title) + |
33 | - "\n<div class='tag_cloud'>\n"+ | |
34 | - tag_cloud( tags, :id, | |
35 | - owner.public_profile_url.merge(:controller => 'profile', :action => 'tags'), | |
36 | - :max_size => 16, :min_size => 9 ) + | |
37 | - "\n</div><!-- end class='tag_cloud' -->\n"; | |
38 | + "\n<div class='tag_cloud'>\n".html_safe+ | |
39 | + tag_cloud( tags, tagname_option, url, :max_size => 16, :min_size => 9 ) + | |
40 | + "\n</div><!-- end class='tag_cloud' -->\n".html_safe | |
38 | 41 | end |
39 | 42 | |
40 | 43 | def footer |
41 | - owner_id = owner.identifier | |
42 | - lambda do | |
43 | - link_to s_('tags|View all'), :profile => owner_id, :controller => 'profile', :action => 'tags' | |
44 | + if owner.class == Environment | |
45 | + lambda do | |
46 | + link_to s_('tags|View all'), | |
47 | + :controller => 'search', :action => 'tags' | |
48 | + end | |
49 | + else | |
50 | + owner_id = owner.identifier | |
51 | + lambda do | |
52 | + link_to s_('tags|View all'), | |
53 | + :profile => owner_id, :controller => 'profile', :action => 'tags' | |
54 | + end | |
44 | 55 | end |
45 | 56 | end |
46 | 57 | ... | ... |
app/models/uploaded_file.rb
... | ... | @@ -113,7 +113,7 @@ class UploadedFile < Article |
113 | 113 | |
114 | 114 | content_tag( |
115 | 115 | 'div', |
116 | - link_to_previous + content_tag('span', _('image %d of %d'), :class => 'total-of-images') % [current_index + 1, total_of_images] + link_to_next, | |
116 | + link_to_previous + (content_tag('span', _('image %d of %d'), :class => 'total-of-images') % [current_index + 1, total_of_images]).html_safe + link_to_next, | |
117 | 117 | :class => 'gallery-navigation' |
118 | 118 | ) |
119 | 119 | end.to_s + | ... | ... |
app/models/user.rb
... | ... | @@ -15,7 +15,7 @@ class User < ActiveRecord::Base |
15 | 15 | # FIXME ugly workaround |
16 | 16 | def self.human_attribute_name(attrib) |
17 | 17 | case attrib.to_sym |
18 | - when :login: return _('Username') | |
18 | + when :login: return [_('Username'), _('Email')].join(' / ') | |
19 | 19 | when :email: return _('e-Mail') |
20 | 20 | else _(self.superclass.human_attribute_name(attrib)) |
21 | 21 | end |
... | ... | @@ -116,10 +116,11 @@ class User < ActiveRecord::Base |
116 | 116 | |
117 | 117 | validates_inclusion_of :terms_accepted, :in => [ '1' ], :if => lambda { |u| ! u.terms_of_use.blank? }, :message => N_('%{fn} must be checked in order to signup.').fix_i18n |
118 | 118 | |
119 | - # Authenticates a user by their login name and unencrypted password. Returns the user or nil. | |
119 | + # Authenticates a user by their login name or email and unencrypted password. Returns the user or nil. | |
120 | 120 | def self.authenticate(login, password, environment = nil) |
121 | 121 | environment ||= Environment.default |
122 | - u = first :conditions => ['login = ? AND environment_id = ? AND activated_at IS NOT NULL', login, environment.id] # need to get the salt | |
122 | + u = self.first :conditions => ['(login = ? OR email = ?) AND environment_id = ? AND activated_at IS NOT NULL', | |
123 | + login, login, environment.id] # need to get the salt | |
123 | 124 | u && u.authenticated?(password) ? u : nil |
124 | 125 | end |
125 | 126 | |
... | ... | @@ -293,7 +294,8 @@ class User < ActiveRecord::Base |
293 | 294 | 'email_domain' => self.enable_email ? self.email_domain : nil, |
294 | 295 | 'friends_list' => friends_list, |
295 | 296 | 'enterprises' => enterprises, |
296 | - 'amount_of_friends' => friends_list.count | |
297 | + 'amount_of_friends' => friends_list.count, | |
298 | + 'chat_enabled' => person.environment.enabled?('xmpp_chat') | |
297 | 299 | } |
298 | 300 | end |
299 | 301 | ... | ... |
app/views/account/_signup_form.rhtml
... | ... | @@ -32,7 +32,8 @@ |
32 | 32 | <span id="signup-domain"><%= environment.default_hostname %>/</span> |
33 | 33 | <div id='signup-login'> |
34 | 34 | <div id='signup-login-field' class='formfield'> |
35 | - <%= required text_field(:user, :login, :id => 'user_login', :onchange => 'this.value = convToValidLogin(this.value);') %> | |
35 | + <%= required text_field(:user, :login, :id => 'user_login', | |
36 | + :onchange => 'this.value = convToValidUsername(this.value);') %> | |
36 | 37 | <div id='url-check'><p> </p></div> |
37 | 38 | </div> |
38 | 39 | <%= content_tag(:small, _('Choose your login name carefully! It will be your network access and you will not be able to change it later.'), :id => 'signup-balloon') %> | ... | ... |
app/views/account/forgot_password.rhtml
... | ... | @@ -5,7 +5,7 @@ |
5 | 5 | <% labelled_form_for :change_password, @change_password, :url => { :action => 'forgot_password' } do |f| %> |
6 | 6 | |
7 | 7 | <%= f.text_field :login, |
8 | - :onchange => 'this.value = convToValidLogin( this.value )' %> | |
8 | + :onchange => 'this.value = convToValidUsername( this.value )' %> | |
9 | 9 | |
10 | 10 | <%= f.text_field :email %> |
11 | 11 | ... | ... |
app/views/admin_panel/site_info.rhtml
... | ... | @@ -4,7 +4,7 @@ |
4 | 4 | |
5 | 5 | <%= render :file => 'shared/tiny_mce' %> |
6 | 6 | |
7 | -<% labelled_form_for :environment, @environment, :url => {:host => @environment.default_hostname, :port => request.port} do |f| %> | |
7 | +<% labelled_form_for :environment, @environment do |f| %> | |
8 | 8 | <% tabs = [] %> |
9 | 9 | <% tabs << {:title => _('Site info'), :id => 'site-info', |
10 | 10 | :content => (render :partial => 'site_info', :locals => {:f => f})} %> | ... | ... |
app/views/box_organizer/_article_block.rhtml
1 | -<div class='article-block-edition'> | |
1 | +<div class="article-block-edition"> | |
2 | 2 | <% if @block.box.owner.kind_of?(Environment) and @block.box.owner.portal_community.nil? %> |
3 | - <p id='no_portal_community'> | |
3 | + <p id="no_portal_community"> | |
4 | 4 | <%= _("You don't have an community defined as the portal community. Define it before use this block properly.") %> |
5 | 5 | </p> |
6 | 6 | <% else %> |
7 | - <% articles = @block.available_articles.select {|article| !article.folder? } %> | |
8 | - <%= select_tag('block[article_id]', options_for_select_with_title(articles.map {|item| [item.path, item.id]}, @block.article ? @block.article.id : nil)) %> | |
7 | + <% | |
8 | + articles = @block.available_articles.select {|a| !a.folder? || a.blog? } | |
9 | + first_text = articles[articles.find_index{|a| a.kind_of? TextArticle}||-1] | |
10 | + selected = @block.article || first_text | |
11 | + %> | |
12 | + <%= select_tag( | |
13 | + 'block[article_id]', | |
14 | + options_for_select_with_title(articles.map {|item| [item.path, item.id]}, selected.id), | |
15 | + :onchange => 'this.changedTo(this.value)' | |
16 | + )%> | |
17 | + <div id="block_blog_options" style="display:none"> | |
18 | + <%= labelled_form_field( | |
19 | + _('Number of posts:'), | |
20 | + text_field_tag('block[posts_per_page]', @block.posts_per_page) | |
21 | + )%> | |
22 | + </div> | |
23 | + <%= labelled_form_field( | |
24 | + _('How to display this content:'), | |
25 | + select_tag( | |
26 | + 'block[visualization_format]', | |
27 | + options_for_select([[_('Lead'), 'short'], [_('Full post'), 'full']], @block.visualization_format) | |
28 | + ) | |
29 | + )%> | |
30 | + <% blogs = @block.available_articles.select{|a|a.blog?} %> | |
31 | + <script> | |
32 | + var select = jQuery("#block_article_id")[0]; | |
33 | + select.blogs = <%= blogs.map{|b| b.id.to_s }.to_json %>; | |
34 | + select.changedTo = function(articleId) { | |
35 | + var blogSelected = this.blogs.indexOf(articleId) != -1; | |
36 | + jQuery("#block_blog_options").toggle(blogSelected); | |
37 | + } | |
38 | + select.changedTo('<%= selected.id %>'); | |
39 | + </script> | |
9 | 40 | <% end %> |
10 | 41 | </div> | ... | ... |
app/views/box_organizer/_block_types.rhtml
... | ... | @@ -1,10 +0,0 @@ |
1 | -<% block_types.in_groups_of(2) do |block1, block2| %> | |
2 | - <div style='float: left; width: 48%; padding-top: 2px;'> | |
3 | - <%= labelled_radio_button(block1.description, :type, block1.name) %> | |
4 | - </div> | |
5 | - <% if block2 %> | |
6 | - <div style='float: left; width: 48%; padding-top: 2px;'> | |
7 | - <%= labelled_radio_button(block2.description, :type, block2.name) %> | |
8 | - </div> | |
9 | - <% end %> | |
10 | -<% end %> |
app/views/box_organizer/_highlights_block.rhtml
1 | 1 | <strong><%= _('Highlights') %></strong> |
2 | -<div id='edit-highlights-block' style='width:450px'> | |
3 | -<table id='highlights' class='noborder'> | |
4 | - <tr><th><%= _('Image') %></th><th><%= _('Address') %></th><th><%= _('Position') %></th><th><%= _('Title') %></th></tr> | |
2 | + | |
3 | +<table class="noborder"><tbody id="highlights-data-table"> | |
4 | + <tr><th><%= _('Image') %></th><th><%= _('Address') %></th><th><%= _('Position') %></th></tr> | |
5 | 5 | <% for image in @block.images do %> |
6 | - <tr> | |
7 | - <td> | |
8 | - <%= select_tag 'block[images][][image_id]', content_tag(:option) + option_groups_from_collection_for_select(@block.folder_choices, :images, :name, :id, :name, image[:image_id].to_i), :style => "width: 100px" %></p> | |
9 | - </td> | |
10 | - <td><%= text_field_tag 'block[images][][address]', image[:address], :class => 'highlight-address', :size => 10 %></td> | |
11 | - <td><%= text_field_tag 'block[images][][position]', image[:position], :class => 'highlight-position', :size => 3 %></td> | |
12 | - <td><%= text_field_tag 'block[images][][title]', image[:title], :class => 'highlight-title', :size => 10 %></td> | |
13 | - </tr> | |
6 | + <%= highlights_block_config_image_fields @block, image %> | |
14 | 7 | <% end %> |
15 | -</table> | |
16 | -</div> | |
8 | +</tbody></table> | |
17 | 9 | |
18 | 10 | <%= link_to_function(_('New highlight'), nil, :class => 'button icon-add with-text') do |page| |
19 | - page.insert_html :bottom, 'highlights', content_tag('tr', | |
20 | - content_tag('td', select_tag('block[images][][image_id]', content_tag(:option) + option_groups_from_collection_for_select(@block.folder_choices, :images, :name, :id, :name), :style => "width: 100px")) + | |
21 | - content_tag('td', text_field_tag('block[images][][address]', nil, :class => 'highlight-address', :size => 10)) + | |
22 | - content_tag('td', text_field_tag('block[images][][position]', nil, :class => 'highlight-position', :size => 3)) + | |
23 | - content_tag('td', text_field_tag('block[images][][title]', nil, :class => 'highlight-position', :size => 10)) | |
24 | - ) + | |
25 | - javascript_tag("$('edit-link-list-block').scrollTop = $('edit-link-list-block').scrollHeight") | |
11 | + page.insert_html :bottom, 'highlights-data-table', highlights_block_config_image_fields(@block) | |
26 | 12 | end %> |
27 | 13 | |
28 | 14 | <%= labelled_form_field _('Image transition:'), select('block', 'interval', [[_('No automatic transition'), 0]] + [1, 2, 3, 4, 5, 10, 20, 30, 60].map {|item| [n_('Every 1 second', 'Every %d seconds', item) % item, item]}) %> | ... | ... |
app/views/box_organizer/add_block.rhtml
1 | -<div style='height:350px'> | |
1 | +<div id="add-block-dialog"> | |
2 | 2 | <% form_tag do %> |
3 | 3 | |
4 | 4 | <p><%= _('In what area do you want to put your new block?') %></p> |
5 | 5 | |
6 | + <div id="box-position"> | |
6 | 7 | <% @boxes.each do |box| %> |
7 | - <%= labelled_radio_button(_("Area %d") % box.position, :box_id, box.id, box.central?, { :class => 'box-position', 'data-position' => box.position }) %> | |
8 | + <% name = box.central? ? _('Main area') : _('Area %d') % box.position %> | |
9 | + <%= labelled_radio_button(name, :box_id, box.id, box.central?, { 'data-position' => box.position }) %> | |
8 | 10 | <% end %> |
11 | + </div> | |
9 | 12 | |
10 | 13 | <script type="text/javascript"> |
11 | - (function ($) { | |
12 | - $(document).ready(function () { | |
13 | - $(".box-position").live('change', function () { | |
14 | - if ($(this).attr('data-position') == '1') { | |
15 | - $('#center-block-types').show(); | |
16 | - $('#side-block-types').hide(); | |
17 | - } else { | |
18 | - $('#center-block-types').hide(); | |
19 | - $('#side-block-types').show(); | |
20 | - }; | |
21 | - }); | |
22 | - })})(jQuery); | |
14 | + jQuery('#box-position input').bind('change', | |
15 | + function () { | |
16 | + showCenter = jQuery(this).attr('data-position') == '1'; | |
17 | + jQuery('#center-block-types').toggle(showCenter); | |
18 | + jQuery('#side-block-types').toggle(!showCenter); | |
19 | + } | |
20 | + ); | |
23 | 21 | </script> |
24 | 22 | |
25 | 23 | <p><%= _('Select the type of block you want to add to your page.') %></p> |
26 | 24 | |
27 | - <div id='center-block-types'> | |
28 | - <%= render :partial => 'block_types', :locals => { :block_types => @center_block_types } %> | |
25 | + <div id="center-block-types" class="block-types"> | |
26 | + <% @center_block_types.each do |block| %> | |
27 | + <div class='block-type'> | |
28 | + <%= labelled_radio_button(block.description, :type, block.name) %> | |
29 | + </div> | |
30 | + <% end %> | |
29 | 31 | </div> |
30 | 32 | |
31 | - <div id='side-block-types' style='display:none'> | |
32 | - <%= render :partial => 'block_types', :locals => { :block_types => @side_block_types } %> | |
33 | + <div id="side-block-types" class="block-types" style="display:none"> | |
34 | + <% @side_block_types.each do |block| %> | |
35 | + <div class='block-type'> | |
36 | + <%= labelled_radio_button(block.description, :type, block.name) %> | |
37 | + </div> | |
38 | + <% end %> | |
33 | 39 | </div> |
34 | 40 | |
35 | 41 | <br style='clear: both'/> | ... | ... |
app/views/box_organizer/edit.rhtml
app/views/box_organizer/index.rhtml
1 | 1 | <h1><%= _('Editing sideboxes')%></h1> |
2 | 2 | |
3 | -<% button_bar do %> | |
3 | +<% button_bar :class=>'design-menu' do %> | |
4 | 4 | <%= colorbox_button('add', _('Add a block'), { :action => 'add_block' }) %> |
5 | 5 | <%= button(:back, _('Back to control panel'), :controller => (profile.nil? ? 'admin_panel': 'profile_editor')) %> |
6 | 6 | <% end %> | ... | ... |
app/views/catalog/index.rhtml
... | ... | @@ -7,13 +7,17 @@ |
7 | 7 | |
8 | 8 | <div class='l-sidebar-left-bar'> |
9 | 9 | <ul> |
10 | - <% if @categories.size > 0 %> | |
10 | + <%= content_tag('li', link_to(_('Homepage'), profile.url), :class => 'catalog-categories-link') %> | |
11 | + <%= content_tag('li', link_to(_('Catalog start'), profile.catalog_url), :class => 'catalog-categories-link') %> | |
12 | + <% if @categories.present? %> | |
11 | 13 | <% @categories.each do |category| %> |
12 | 14 | <%= category_link(category) %> |
13 | 15 | <%= category_sub_links(category) %> |
14 | 16 | <% end %> |
17 | + <% elsif @category.present? %> | |
18 | + <%= content_tag('li', _('There are no sub-categories for %s') % @category.name, :id => 'catalog-categories-notice') %> | |
15 | 19 | <% else %> |
16 | - <%= content_tag('li', _('There are no sub-categories for %s') % @category.name, :style => 'color: #555753; padding-bottom: 0.5em;') %> | |
20 | + <%= content_tag('li', _('There are no categories available.'), :id => 'catalog-categories-notice') %> | |
17 | 21 | <% end %> |
18 | 22 | </ul> |
19 | 23 | </div> |
... | ... | @@ -64,20 +68,20 @@ |
64 | 68 | |
65 | 69 | <% if product.description %> |
66 | 70 | <li class="product-description expand-box"> |
67 | - <span id="product-description-button"><%= _('description') %></span> | |
68 | - <div> | |
71 | + <span class="product-description-button"><%= _('description') %></span> | |
72 | + <div class="float-box"> | |
69 | 73 | <div class="arrow"></div> |
70 | - <div class="content" id="product-description"><%= txt2html(product.description || '') %></div> | |
74 | + <div class="content"><%= product.description %></div> | |
71 | 75 | </div> |
72 | 76 | </li> |
73 | 77 | <% end %> |
74 | 78 | |
75 | 79 | <% if product.price_described? %> |
76 | 80 | <li class="product-price-composition expand-box"> |
77 | - <span id="product-price-composition-button"><%= _('price composition') %></span> | |
78 | - <div> | |
81 | + <span class="product-price-composition-button"><%= _('price composition') %></span> | |
82 | + <div class="float-box"> | |
79 | 83 | <div class="arrow"></div> |
80 | - <div class="content" id="product-price-composition"> | |
84 | + <div class="content"> | |
81 | 85 | <% product.inputs.relevant_to_price.each do |i| %> |
82 | 86 | <div class="search-product-input-dots-to-price"> |
83 | 87 | <div class="search-product-input-name"><%= i.product_category.name %></div> |
... | ... | @@ -98,9 +102,9 @@ |
98 | 102 | <% if product.inputs.count > 0 %> |
99 | 103 | <li class="product-inputs expand-box"> |
100 | 104 | <span id="inputs-button"><%= _('inputs and raw materials') %></span> |
101 | - <div> | |
105 | + <div class="float-box"> | |
102 | 106 | <div class="arrow"></div> |
103 | - <div class="content" id="inputs-description"> | |
107 | + <div class="content"> | |
104 | 108 | <% product.inputs.each do |i| %> |
105 | 109 | <div> |
106 | 110 | <%= _('%{amount_used} %{unit} of') % {:amount_used => i.amount_used, :unit => i.unit.singular} + ' ' if i.has_all_price_details? %> | ... | ... |
app/views/cms/_text_editor_sidebar.rhtml
... | ... | @@ -9,7 +9,12 @@ |
9 | 9 | <div id='media-upload-form'> |
10 | 10 | <% form_tag({ :action => 'media_upload' }, :multipart => true) do %> |
11 | 11 | <div class='formfield'> |
12 | - <%= select_profile_folder(_('Choose folder to upload files:'), :parent_id, profile) %> | |
12 | + <% default_folder = content_id_to_str default_folder_for_image_upload(profile) %> | |
13 | + <%= select_profile_folder( | |
14 | + _('Choose folder to upload files:'), | |
15 | + :parent_id, profile, default_folder, {}, {}, | |
16 | + "type='Folder' or type='Gallery'" | |
17 | + ) %> | |
13 | 18 | </div> |
14 | 19 | <p><%= file_field_tag('file1') %></p> |
15 | 20 | <p><%= file_field_tag('file2') %></p> | ... | ... |
app/views/cms/select_article_type.rhtml
1 | +<div class="select-article-type"> | |
2 | + | |
1 | 3 | <h2> <%= _('Choose the type of content:') %> </h2> |
2 | 4 | |
3 | -<ul id="article_types"> | |
5 | +<ul class="article-types"> | |
4 | 6 | <% for type in @article_types %> |
5 | 7 | <% action = type[:class].name == 'UploadedFile' ? {:action => 'upload_files'} : {:action => 'new', :type => type[:class].name} %> |
6 | 8 | <% content_tag('a', :href => url_for(action.merge(:parent_id => @parent_id, :back_to => @back_to))) do %> |
... | ... | @@ -14,3 +16,5 @@ |
14 | 16 | <br style="clear:both" /> |
15 | 17 | |
16 | 18 | <%= colorbox_close_button(_('Cancel')) %> |
19 | + | |
20 | +</div> | ... | ... |
app/views/content_viewer/blog_page.rhtml
1 | -<% add_rss_feed_to_head(@page.name, @page.feed.url) if @page.blog? && @page.feed %> | |
1 | +<% add_rss_feed_to_head(blog.name, blog.feed.url) if blog.blog? && blog.feed %> | |
2 | 2 | |
3 | -<%= content_tag('em', _('(external feed was not loaded yet)'), :id => 'external-feed-info', :class => 'metadata') if @page.blog? && @page.external_feed && @page.external_feed.enabled && @page.external_feed.fetched_at.nil? %> | |
3 | +<%= content_tag('em', _('(external feed was not loaded yet)'), :id => 'external-feed-info', :class => 'metadata') if blog.blog? && blog.external_feed && blog.external_feed.enabled && blog.external_feed.fetched_at.nil? %> | |
4 | 4 | |
5 | 5 | <div> |
6 | 6 | <div class='blog-description'> |
7 | - <%= @page.body %> | |
7 | + <%= blog.body %> | |
8 | 8 | </div> |
9 | 9 | </div> |
10 | 10 | <hr class="pre-posts"/> |
11 | 11 | <div class="blog-posts"> |
12 | - <%= (@page.empty? ? content_tag('em', _('(no posts)')) : list_posts(@posts, @page.visualization_format)) %> | |
12 | + <%= | |
13 | + posts = @posts | |
14 | + format = blog.visualization_format | |
15 | + if inside_block | |
16 | + posts = blog.posts.paginate(:page=>1, :per_page=>inside_block.posts_per_page) | |
17 | + format = inside_block.visualization_format | |
18 | + end | |
19 | + (blog.empty? ? content_tag('em', _('(no posts)')) : list_posts(posts, format)) | |
20 | + %> | |
13 | 21 | </div> | ... | ... |
app/views/content_viewer/view_page.rhtml
... | ... | @@ -66,7 +66,6 @@ |
66 | 66 | addthis_options = '<%= escape_javascript( NOOSFERO_CONF['addthis_options'] ) %>'; |
67 | 67 | </script> |
68 | 68 | <a href="http://www.addthis.com/bookmark.php" id="bt_addThis" target="_blank" onmouseover="return addthis_open(this, '', '[URL]')" onmouseout="addthis_close()" onclick="return addthis_sendto()"><%= addthis_image_tag %></a> |
69 | -<script type="text/javascript" src="http://s7.addthis.com/js/152/addthis_widget.js"></script> | |
70 | 69 | </div> |
71 | 70 | <% end %> |
72 | 71 | |
... | ... | @@ -96,7 +95,7 @@ |
96 | 95 | <% end %> |
97 | 96 | |
98 | 97 | <% if @page.accept_comments? && @comments_count > 1 %> |
99 | - <p class="post-comment-button"><a href="#comment_form" onclick="jQuery('#page-comment-form h4').first().trigger('click')"><%= _('Post a comment') %></a></p> | |
98 | + <%= link_to(_('Post a comment'), '#', :class => 'display-comment-form', :id => 'top-post-comment-button') %> | |
100 | 99 | <% end %> |
101 | 100 | |
102 | 101 | <ul class="article-comments-list"> | ... | ... |
app/views/favorite_enterprises/index.rhtml
... | ... | @@ -5,7 +5,7 @@ |
5 | 5 | <ul class="profile-list"> |
6 | 6 | <% @favorite_enterprises.each do |enterprise| %> |
7 | 7 | <li> |
8 | - <%= link_to_profile profile_image(enterprise) + '<br/>' + enterprise.name, | |
8 | + <%= link_to_profile profile_image(enterprise) + '<br/>'.html_safe + enterprise.name, | |
9 | 9 | enterprise.identifier, :class => 'profile-link' %> |
10 | 10 | <%# profile_image_link enterprise, :portrait, 'div' %> |
11 | 11 | <div class="controll"> | ... | ... |
... | ... | @@ -0,0 +1,24 @@ |
1 | +<div id="user"> | |
2 | + <span class='logged-in' style='display: none;'> | |
3 | + <%= usermenu_logged_in %> | |
4 | + </span> | |
5 | + <span class='not-logged-in' style='display: none'> | |
6 | + | |
7 | + <%= _("<span class='login'>%s</span>") % thickbox_inline_popup_link('<i class="icon-menu-login"></i><strong>' + _('Login') + '</strong>', login_url, 'inlineLoginBox', :id => 'link_login') %> | |
8 | + <%= @plugins.dispatch(:alternative_authentication_link).collect { |content| instance_eval(&content) }.join("") %> | |
9 | + | |
10 | + <div id='inlineLoginBox' style='display: none;'> | |
11 | + <%= render :file => 'account/login', :locals => { :is_thickbox => true } %> | |
12 | + </div> | |
13 | + | |
14 | + <% unless @plugins.dispatch(:allow_user_registration).include?(false) %> | |
15 | + <%= _("<span class='or'>or</span> <span class='signup'>%s</span>") % link_to('<strong>' + _('Sign up') + '</strong>', :controller => 'account', :action => 'signup')%> | |
16 | + <% end %> | |
17 | + | |
18 | + </span> | |
19 | + <form action="/search" id="top-search" class="search_form clean" method="get"> | |
20 | + <input name="query" size="15" title="<%=_('Search...')%>" onfocus="this.form.className='focused';" onblur="this.form.className=''" /> | |
21 | + <div><%=_('Press <strong>Enter</strong> to send the search query.')%></div> | |
22 | + <%= javascript_tag 'jQuery("#user form input").hint();' %> | |
23 | + </form> | |
24 | +</div><!-- end id="user" --> | ... | ... |
app/views/layouts/application-ng.rhtml
... | ... | @@ -8,23 +8,10 @@ |
8 | 8 | <meta name="description" content="<%= @environment.name %>" /> |
9 | 9 | <link rel="shortcut icon" href="<%= image_path(theme_favicon) %>" type="image/x-icon" /> |
10 | 10 | <%= noosfero_javascript %> |
11 | - <%= stylesheet_link_tag noosfero_stylesheets, :cache => 'cache' %> | |
12 | - <%= stylesheet_link_tag template_stylesheet_path %> | |
13 | - <%= stylesheet_link_tag icon_theme_stylesheet_path %> | |
14 | - <%= stylesheet_link_tag jquery_ui_theme_stylesheet_path %> | |
15 | - <% | |
16 | - plugins_stylesheets = @plugins.select(&:stylesheet?).map { |plugin| plugin.class.public_path('style.css') } | |
17 | - %> | |
18 | - <%= stylesheet_link_tag(plugins_stylesheets, :cache => 'cache/plugins-' + Digest::MD5.hexdigest(plugins_stylesheets.to_s)) unless plugins_stylesheets.empty? %> | |
19 | - <%= stylesheet_link_tag theme_stylesheet_path %> | |
11 | + <%= noosfero_stylesheets %> | |
20 | 12 | |
21 | 13 | <%# Add custom tags/styles/etc via content_for %> |
22 | 14 | <%= yield :head %> |
23 | - <%= javascript_tag('render_all_jquery_ui_widgets()') %> | |
24 | - <% | |
25 | - plugins_javascripts = @plugins.map { |plugin| plugin.js_files.map { |js| plugin.class.public_path(js) } }.flatten | |
26 | - %> | |
27 | - <%= javascript_include_tag(plugins_javascripts, :cache => 'cache/plugins-' + Digest::MD5.hexdigest(plugins_javascripts.to_s)) unless plugins_javascripts.empty? %> | |
28 | 15 | <%= |
29 | 16 | @plugins.dispatch(:head_ending).collect do |content| |
30 | 17 | content.respond_to?(:call) ? content.call : content |
... | ... | @@ -35,15 +22,9 @@ |
35 | 22 | DEFAULT_LOADING_MESSAGE = <%="'#{ _('loading...') }'" %>; |
36 | 23 | </script> |
37 | 24 | </head> |
38 | - <body class="<%= | |
39 | - # Identify the current controller and action for the CSS: | |
40 | - " controller-"+ @controller.controller_name() + | |
41 | - " action-"+ @controller.controller_name() +"-"+ @controller.action_name() + | |
42 | - " template-"+ ( profile.nil? ? "default" : profile.layout_template ) + | |
43 | - (!profile.nil? && profile.is_on_homepage?(request.path,@page) ? " profile-homepage" : "") | |
44 | - %>" > | |
45 | - | |
25 | + <body class="<%= body_classes %>"> | |
46 | 26 | <a href="#content" id="link-go-content"><span><%= _("Go to the content") %></span></a> |
27 | + | |
47 | 28 | <%= |
48 | 29 | @plugins.dispatch(:body_beginning).collect do |content| |
49 | 30 | content.respond_to?(:call) ? content.call : content |
... | ... | @@ -55,31 +36,7 @@ |
55 | 36 | <%= theme_header %> |
56 | 37 | </div> |
57 | 38 | <div id="wrap-2"> |
58 | - <div id="user"> | |
59 | - <span class='logged-in' style='display: none;'> | |
60 | - <%= usermenu_logged_in %> | |
61 | - </span> | |
62 | - <span class='not-logged-in' style='display: none'> | |
63 | - | |
64 | - <%= _("<span class='login'>%s</span>") % thickbox_inline_popup_link('<i class="icon-menu-login"></i><strong>' + _('Login') + '</strong>', login_url, 'inlineLoginBox', :id => 'link_login') %> | |
65 | - <%= @plugins.dispatch(:alternative_authentication_link).collect { |content| instance_eval(&content) }.join("") %> | |
66 | - | |
67 | - <div id='inlineLoginBox' style='display: none;'> | |
68 | - <%= render :file => 'account/login', :locals => { :is_thickbox => true } %> | |
69 | - </div> | |
70 | - | |
71 | - <% unless @plugins.dispatch(:allow_user_registration).include?(false) %> | |
72 | - <%= _("<span class='or'>or</span> <span class='signup'>%s</span>") % link_to('<strong>' + _('Sign up') + '</strong>', :controller => 'account', :action => 'signup')%> | |
73 | - <% end %> | |
74 | - | |
75 | - </span> | |
76 | - <form action="/search" class="search_form" method="get" class="clean"> | |
77 | - <input name="query" size="15" title="<%=_('Search...')%>" onfocus="this.form.className='focused';" onblur="this.form.className=''" /> | |
78 | - <div><%=_('Press <strong>Enter</strong> to send the search query.')%></div> | |
79 | - <%= javascript_tag 'jQuery("#user form input").hint();' %> | |
80 | - </form> | |
81 | - </div><!-- end id="user" --> | |
82 | - | |
39 | + <%= render :partial => 'layouts/user' %> | |
83 | 40 | <h1 id="site-title"> |
84 | 41 | <%= theme_site_title %> |
85 | 42 | </h1> |
... | ... | @@ -103,5 +60,6 @@ |
103 | 60 | </div><!-- end id="theme-footer" --> |
104 | 61 | <%= noosfero_layout_features %> |
105 | 62 | <%= theme_javascript_ng %> |
63 | + <%= addthis_javascript %> | |
106 | 64 | </body> |
107 | 65 | </html> | ... | ... |
app/views/map_balloon/product.rhtml
app/views/profile/_profile_wall.rhtml
1 | 1 | <h3><%= _("%s's wall") % @profile.name %></h3> |
2 | 2 | <div id='leave_scrap'> |
3 | 3 | <%= flash[:error] %> |
4 | - <% form_remote_tag :url => {:controller => 'profile', :action => 'leave_scrap', :tab_action => 'wall' }, :update => 'profile_activities', :success => "$('leave_scrap_content').value=''" do %> | |
4 | + <% form_remote_tag :url => {:controller => 'profile', :action => 'leave_scrap', :tab_action => 'wall' }, :update => 'profile_activities', :success => "$('leave_scrap_content').value=''", :complete => "jQuery('#leave_scrap_form').removeClass('loading').find('*').attr('disabled', false)", :loading => "jQuery('#leave_scrap_form').addClass('loading').find('*').attr('disabled', true)", :html => {:id => 'leave_scrap_form' } do %> | |
5 | 5 | <%= limited_text_area :scrap, :content, 420, 'leave_scrap_content', :cols => 50, :rows => 2 %> |
6 | 6 | <%= submit_button :new, _('Share') %> |
7 | 7 | <% end %> | ... | ... |
app/views/profile_members/_manage_roles.html.erb
... | ... | @@ -13,11 +13,11 @@ |
13 | 13 | |
14 | 14 | <% @roles.each do |role| %> |
15 | 15 | <% search_url = url_for(:action => 'search_user', :profile => profile.identifier, :role => role.id) %> |
16 | - <% @pre_population ||= profile.members_by_role_to_json(role) %> | |
16 | + <% pre_population = params[:action] == 'last_admin' ? [].to_json : profile.members_by_role_to_json(role) %> | |
17 | 17 | <script type="text/javascript"> |
18 | 18 | jQuery(<%= ('#search_' + role.key).to_json %>) |
19 | 19 | .tokenInput("<%= search_url %>", { |
20 | - prePopulate: <%= @pre_population %>, | |
20 | + prePopulate: <%= pre_population %>, | |
21 | 21 | hintText: <%= _('Type in a search term for users').to_json %>, |
22 | 22 | noResultsText: <%= _('No results').to_json %>, |
23 | 23 | searchingText: <%= _('Searching...').to_json %>, | ... | ... |
app/views/search/_article.rhtml
... | ... | @@ -1,12 +0,0 @@ |
1 | -<li class="search-article-item article-item"> | |
2 | - <%= link_to(article.title, article.url, :class => "search-result-title") %> | |
3 | - <div class="search-content-first-column"> | |
4 | - <%= render :partial => 'image', :object => article %> | |
5 | - </div> | |
6 | - <table class="noborder search-content-second-column"> | |
7 | - <%= render :partial => 'article_common', :object => article %> | |
8 | - </table> | |
9 | - <%= render :partial => 'article_last_change', :object => article %> | |
10 | - | |
11 | - <div style="clear:both"></div> | |
12 | -</li> |
app/views/search/_blog.rhtml
... | ... | @@ -1,24 +0,0 @@ |
1 | -<li class="search-blog article-item"> | |
2 | - <%= link_to blog.title, blog.view_url, :class => 'search-result-title' %> | |
3 | - <div class="search-content-first-column"> | |
4 | - <%= render :partial => 'image', :object => blog %> | |
5 | - </div> | |
6 | - <table class="noborder search-content-second-column"> | |
7 | - <tr class="search-blog-items"> | |
8 | - <td class="search-field-label"><%= _("Last posts") %></td> | |
9 | - | |
10 | - <% r = blog.children.find(:all, :order => :updated_at, :conditions => ['type != ?', 'RssFeed']).last(3) %> | |
11 | - <td class="<%= "search-field-none" if r.empty? %>"> | |
12 | - <% r.each do |a| %> | |
13 | - <%= link_to a.title, a.view_url, :class => 'search-blog-sample-item '+icon_for_article(a) %> | |
14 | - <% end %> | |
15 | - <%= _('None') if r.empty? %> | |
16 | - </td> | |
17 | - </tr> | |
18 | - | |
19 | - <%= render :partial => 'article_common', :object => blog %> | |
20 | - </table> | |
21 | - <%= render :partial => 'article_last_change', :object => blog %> | |
22 | - | |
23 | - <div style="clear: both;"/></div> | |
24 | -</li> |
app/views/search/_content.rhtml
app/views/search/_display_results.rhtml
1 | 1 | <div id="search-results" class="<%= !multiple_search? ? 'only-one-result-box' : 'multiple-results-boxes' %>"> |
2 | 2 | <% @order.each do |name| %> |
3 | - <% results = @results[name] %> | |
4 | - <% empty = results.nil? || results.empty? %> | |
3 | + <% search = @searches[name] %> | |
5 | 4 | |
6 | - <div class="search-results-<%= name %> search-results-box <%= "search-results-empty" if empty %>"> | |
7 | - <% if not empty %> | |
8 | - <% partial = partial_for_class(results.first.class.class_name.constantize) %> | |
5 | + <div class="search-results-<%= name %> search-results-box <%= "search-results-empty" if search[:results].blank? %>"> | |
6 | + <% if !search[:results].blank? %> | |
9 | 7 | |
10 | - <% if multiple_search? %> | |
8 | + <% if multiple_search?(@searches) %> | |
11 | 9 | <h3><%= @names[name] %></h3> |
12 | - <% if results.total_entries > SearchController::MULTIPLE_SEARCH_LIMIT %> | |
13 | - <%= link_to(_('see all (%d)') % results.total_entries, params.merge(:action => name), :class => 'see-more' ) %> | |
10 | + <% if search[:results].total_entries > SearchController::MULTIPLE_SEARCH_LIMIT %> | |
11 | + <%= link_to(_('see all (%d)') % search[:results].total_entries, params.merge(:action => name), :class => 'see-more' ) %> | |
14 | 12 | <% end %> |
15 | 13 | <% end %> |
16 | 14 | |
17 | - <div class="search-results-innerbox search-results-type-<%= partial %> <%= 'common-profile-list-block' if partial == 'profile' %>"> | |
15 | + <% display = display_filter(name, params[:display]) %> | |
16 | + | |
17 | + <div class="search-results-innerbox search-results-type-<%= name.to_s.singularize %> <%= 'common-profile-list-block' if [:enterprises, :people, :communities].include?(name) %>"> | |
18 | 18 | <ul> |
19 | - <% results.each do |hit| %> | |
20 | - <%= render :partial => partial_for_class(hit.class), :object => hit %> | |
21 | - <% end %> | |
19 | + <% search[:results].each do |hit| %> | |
20 | + <% partial = partial_for_class(hit.class, display) %> | |
21 | + <% variable_name = partial.gsub("#{display}_", '').to_sym %> | |
22 | + <%= render :partial => partial, :locals => {variable_name => hit} %> | |
23 | + <% end %> | |
22 | 24 | </ul> |
23 | 25 | </div> |
24 | 26 | <% else %> | ... | ... |
app/views/search/_event.rhtml
... | ... | @@ -1,25 +0,0 @@ |
1 | -<li class="search-event-item article-item"> | |
2 | -<%= link_to(event.title, event.url, :class => "search-result-title") %> | |
3 | -<div class="search-content-first-column"> | |
4 | - <%= render :partial => 'image', :object => event %> | |
5 | -</div> | |
6 | -<table class="noborder search-content-second-column"> | |
7 | - <% if event.start_date %> | |
8 | - <tr class="search-article-event-date"> | |
9 | - <td class="search-field-label"><%= _('Start date') %></td> | |
10 | - <td class="article-item-date"><%= event.start_date %></td> | |
11 | - </tr> | |
12 | - <% end %> | |
13 | - <% if event.end_date %> | |
14 | - <tr class="search-article-event-date"> | |
15 | - <td class="search-field-label"><%= _('End date') %></td> | |
16 | - <td class="article-item-date"><%= event.end_date %></td> | |
17 | - </tr> | |
18 | - <% end %> | |
19 | - | |
20 | - <%= render :partial => 'article_common', :object => event %> | |
21 | -</table> | |
22 | -<%= render :partial => 'article_last_change', :object => event %> | |
23 | - | |
24 | -<div style="clear: both"></div> | |
25 | -</li> |
app/views/search/_facets_menu.rhtml
... | ... | @@ -1,36 +0,0 @@ |
1 | -<% less_options_limit = 8 %> | |
2 | - | |
3 | -<div id="facets-menu"> | |
4 | - <% @asset_class.map_facets_for(environment).each do |facet| %> | |
5 | - | |
6 | - <div id="facet-menu-<%= facet[:id].to_s %>" class="facet-menu"> | |
7 | - <div class="facet-menu-label"> | |
8 | - <%= @asset_class.facet_label(facet) %> | |
9 | - </div> | |
10 | - | |
11 | - <% results = @asset_class.map_facet_results(facet, params[:facet], @facets, @all_facets, :limit => less_options_limit) %> | |
12 | - <% facet_count = results.total_entries %> | |
13 | - | |
14 | - <% if facet_count > 0 %> | |
15 | - <div class="facet-menu-options facet-menu-more-options" style="display: none"> | |
16 | - </div> | |
17 | - | |
18 | - <div class="facet-menu-options facet-menu-less-options"> | |
19 | - <% results.each do |id, label, count| %> | |
20 | - <%= facet_link_html(facet, params, id, label, count) %><br /> | |
21 | - <% end %> | |
22 | - </div> <br /> | |
23 | - | |
24 | - <% if facet_count > less_options_limit %> | |
25 | - <%= link_to_function _("Options"), | |
26 | - "facet_options_toggle('#{facet[:id].to_s}', '#{url_for(params.merge(:action => 'facets_browse', :facet_id => facet[:id], :asset => @asset, :escape => false))}'); " + | |
27 | - "jQuery(this).toggleClass('facet-less-options')", :class => "facet-options-toggle" %> | |
28 | - <br /> | |
29 | - <% end %> | |
30 | - | |
31 | - <% else %> | |
32 | - <span class="facet-any-result-found"><%= _("No filter available") %></span> | |
33 | - <% end %> | |
34 | - </div> | |
35 | - <% end %> | |
36 | -</div> |
app/views/search/_facets_unselect_menu.rhtml
app/views/search/_folder.rhtml
... | ... | @@ -1,24 +0,0 @@ |
1 | -<li class="search-folder-item article-item"> | |
2 | - <%= link_to folder.title, folder.view_url, :class => 'search-result-title' %> | |
3 | - <div class="search-content-first-column"> | |
4 | - <%= render :partial => 'image', :object => folder %> | |
5 | - </div> | |
6 | - <table class="noborder search-content-second-column"> | |
7 | - <tr class="search-folder-items"> | |
8 | - <td class="search-field-label"><%= _("Last items") %></td> | |
9 | - | |
10 | - <% r = folder.children.last(3) %> | |
11 | - <td class="<%= "search-field-none" if r.empty? %>"> | |
12 | - <% r.each do |a| %> | |
13 | - <%= link_to a.title, a.view_url, :class => 'search-folder-sample-item '+icon_for_article(a) %> | |
14 | - <% end %> | |
15 | - <%= _('None') if r.empty? %> | |
16 | - </td> | |
17 | - </tr> | |
18 | - | |
19 | - <%= render :partial => 'article_common', :object => folder %> | |
20 | - </table> | |
21 | - <%= render :partial => 'article_last_change', :object => folder %> | |
22 | - | |
23 | - <div style="clear:both"></div> | |
24 | -</li> |
app/views/search/_forum.rhtml
... | ... | @@ -1,24 +0,0 @@ |
1 | -<li class="search-forum-item article-item"> | |
2 | - <%= link_to forum.title, forum.view_url, :class => 'search-result-title' %> | |
3 | - <div class="search-content-first-column"> | |
4 | - <%= render :partial => 'image', :object => forum %> | |
5 | - </div> | |
6 | - <table class="noborder search-content-second-column"> | |
7 | - <tr class="search-forum-items"> | |
8 | - <td class="search-field-label"><%= _("Last topics") %></td> | |
9 | - | |
10 | - <% r = forum.children.find(:all, :order => :updated_at, :conditions => ['type != ?', 'RssFeed']).last(3) %> | |
11 | - <td class="<%= "search-field-none" if r.empty? %>"> | |
12 | - <% r.each do |a| %> | |
13 | - <%= link_to a.title, a.view_url, :class => 'search-forum-sample-item '+icon_for_article(a) %> | |
14 | - <% end %> | |
15 | - <%= _('None') if r.empty? %> | |
16 | - </td> | |
17 | - </tr> | |
18 | - | |
19 | - <%= render :partial => 'article_common', :object => forum %> | |
20 | - </table> | |
21 | - <%= render :partial => 'article_last_change', :object => forum %> | |
22 | - | |
23 | - <div style="clear:both"></div> | |
24 | -</li> |
... | ... | @@ -0,0 +1,12 @@ |
1 | +<li class="search-article-item article-item"> | |
2 | + <%= link_to(article.title, article.url, :class => "search-result-title") %> | |
3 | + <div class="search-content-first-column"> | |
4 | + <%= render :partial => 'image', :object => article %> | |
5 | + </div> | |
6 | + <table class="noborder search-content-second-column"> | |
7 | + <%= render :partial => 'article_common', :object => article %> | |
8 | + </table> | |
9 | + <%= render :partial => 'article_last_change', :object => article %> | |
10 | + | |
11 | + <div style="clear:both"></div> | |
12 | +</li> | ... | ... |
... | ... | @@ -0,0 +1,24 @@ |
1 | +<li class="search-blog article-item"> | |
2 | + <%= link_to blog.title, blog.view_url, :class => 'search-result-title' %> | |
3 | + <div class="search-content-first-column"> | |
4 | + <%= render :partial => 'image', :object => blog %> | |
5 | + </div> | |
6 | + <table class="noborder search-content-second-column"> | |
7 | + <tr class="search-blog-items"> | |
8 | + <td class="search-field-label"><%= _("Last posts") %></td> | |
9 | + | |
10 | + <% r = blog.children.find(:all, :order => :updated_at, :conditions => ['type != ?', 'RssFeed']).last(3) %> | |
11 | + <td class="<%= "search-field-none" if r.empty? %>"> | |
12 | + <% r.each do |a| %> | |
13 | + <%= link_to a.title, a.view_url, :class => 'search-blog-sample-item '+icon_for_article(a) %> | |
14 | + <% end %> | |
15 | + <%= _('None') if r.empty? %> | |
16 | + </td> | |
17 | + </tr> | |
18 | + | |
19 | + <%= render :partial => 'article_common', :object => blog %> | |
20 | + </table> | |
21 | + <%= render :partial => 'article_last_change', :object => blog %> | |
22 | + | |
23 | + <div style="clear: both;"/></div> | |
24 | +</li> | ... | ... |
... | ... | @@ -0,0 +1,38 @@ |
1 | +<li class="search-profile-item"> | |
2 | + <div class="search-enterprise-item"> | |
3 | + <div class="search-enterprise-item-column-left"> | |
4 | + <%= profile_image_link enterprise, :portrait, 'div', | |
5 | + @filter == 'more_recent' ? enterprise.send(@filter + '_label') + show_date(enterprise.created_at) : enterprise.send(@filter + '_label') %> | |
6 | + </div> | |
7 | + <div class="search-enterprise-item-column-right"> | |
8 | + <%= link_to_homepage(enterprise.name, enterprise.identifier, :class => "search-result-title") %> | |
9 | + <div class="search-enterprise-description"> | |
10 | + <% if enterprise.description %> | |
11 | + <% body_stripped = strip_tags(enterprise.description) %> | |
12 | + <% elsif enterprise.home_page and enterprise.home_page.body %> | |
13 | + <% body_stripped = strip_tags(enterprise.home_page.body) %> | |
14 | + <% end %> | |
15 | + <%= excerpt(body_stripped, body_stripped.first(3), 200) if body_stripped %> | |
16 | + </div> | |
17 | + <div class="search-enterprise-region"> | |
18 | + <span class="search-enterprise-region-label"><%= _("City") %></span> | |
19 | + <% if enterprise.region %> | |
20 | + <span class="search-enterprise-region-name"><%= city_with_state(enterprise.region) %></span> | |
21 | + <% end %> | |
22 | + </div> | |
23 | + | |
24 | + <div class="search-enterprise-categorization"> | |
25 | + <% enterprise.top_level_categorization.each do |parent, children| %> | |
26 | + <div class="search-enterprise-category-<%=parent.id%> search-enterprise-category"> | |
27 | + <span class="search-enterprise-categorization-parent"><%= parent.name %></span> | |
28 | + <span class="search-enterprise-categorization-children"> | |
29 | + <%= children.collect(&:name).join(', ') %> | |
30 | + </span> | |
31 | + </div> | |
32 | + <% end %> | |
33 | + </div> | |
34 | + </div> | |
35 | + | |
36 | + <hr class="clearfix" /> | |
37 | + </div> | |
38 | +</li> | ... | ... |
... | ... | @@ -0,0 +1,25 @@ |
1 | +<li class="search-event-item article-item"> | |
2 | +<%= link_to(event.title, event.url, :class => "search-result-title") %> | |
3 | +<div class="search-content-first-column"> | |
4 | + <%= render :partial => 'image', :object => event %> | |
5 | +</div> | |
6 | +<table class="noborder search-content-second-column"> | |
7 | + <% if event.start_date %> | |
8 | + <tr class="search-article-event-date"> | |
9 | + <td class="search-field-label"><%= _('Start date') %></td> | |
10 | + <td class="article-item-date"><%= event.start_date %></td> | |
11 | + </tr> | |
12 | + <% end %> | |
13 | + <% if event.end_date %> | |
14 | + <tr class="search-article-event-date"> | |
15 | + <td class="search-field-label"><%= _('End date') %></td> | |
16 | + <td class="article-item-date"><%= event.end_date %></td> | |
17 | + </tr> | |
18 | + <% end %> | |
19 | + | |
20 | + <%= render :partial => 'article_common', :object => event %> | |
21 | +</table> | |
22 | +<%= render :partial => 'article_last_change', :object => event %> | |
23 | + | |
24 | +<div style="clear: both"></div> | |
25 | +</li> | ... | ... |
... | ... | @@ -0,0 +1,24 @@ |
1 | +<li class="search-folder-item article-item"> | |
2 | + <%= link_to folder.title, folder.view_url, :class => 'search-result-title' %> | |
3 | + <div class="search-content-first-column"> | |
4 | + <%= render :partial => 'image', :object => folder %> | |
5 | + </div> | |
6 | + <table class="noborder search-content-second-column"> | |
7 | + <tr class="search-folder-items"> | |
8 | + <td class="search-field-label"><%= _("Last items") %></td> | |
9 | + | |
10 | + <% r = folder.children.last(3) %> | |
11 | + <td class="<%= "search-field-none" if r.empty? %>"> | |
12 | + <% r.each do |a| %> | |
13 | + <%= link_to a.title, a.view_url, :class => 'search-folder-sample-item '+icon_for_article(a) %> | |
14 | + <% end %> | |
15 | + <%= _('None') if r.empty? %> | |
16 | + </td> | |
17 | + </tr> | |
18 | + | |
19 | + <%= render :partial => 'article_common', :object => folder %> | |
20 | + </table> | |
21 | + <%= render :partial => 'article_last_change', :object => folder %> | |
22 | + | |
23 | + <div style="clear:both"></div> | |
24 | +</li> | ... | ... |
... | ... | @@ -0,0 +1,24 @@ |
1 | +<li class="search-forum-item article-item"> | |
2 | + <%= link_to forum.title, forum.view_url, :class => 'search-result-title' %> | |
3 | + <div class="search-content-first-column"> | |
4 | + <%= render :partial => 'image', :object => forum %> | |
5 | + </div> | |
6 | + <table class="noborder search-content-second-column"> | |
7 | + <tr class="search-forum-items"> | |
8 | + <td class="search-field-label"><%= _("Last topics") %></td> | |
9 | + | |
10 | + <% r = forum.children.find(:all, :order => :updated_at, :conditions => ['type != ?', 'RssFeed']).last(3) %> | |
11 | + <td class="<%= "search-field-none" if r.empty? %>"> | |
12 | + <% r.each do |a| %> | |
13 | + <%= link_to a.title, a.view_url, :class => 'search-forum-sample-item '+icon_for_article(a) %> | |
14 | + <% end %> | |
15 | + <%= _('None') if r.empty? %> | |
16 | + </td> | |
17 | + </tr> | |
18 | + | |
19 | + <%= render :partial => 'article_common', :object => forum %> | |
20 | + </table> | |
21 | + <%= render :partial => 'article_last_change', :object => forum %> | |
22 | + | |
23 | + <div style="clear:both"></div> | |
24 | +</li> | ... | ... |
... | ... | @@ -0,0 +1,13 @@ |
1 | +<li class="search-gallery article-item"> | |
2 | + <%= link_to gallery.title, gallery.view_url, :class => 'search-result-title' %> | |
3 | + <div class="search-content-first-column"> | |
4 | + <%= render :partial => 'image', :object => gallery %> | |
5 | + </div> | |
6 | + <table class="noborder search-content-second-column"> | |
7 | + <%= render :partial => 'article_common', :object => gallery %> | |
8 | + </table> | |
9 | + <%= render :partial => 'article_last_change', :object => gallery %> | |
10 | + | |
11 | + <div style="clear: both"></div> | |
12 | +</li> | |
13 | + | ... | ... |
... | ... | @@ -0,0 +1,85 @@ |
1 | +<% extra_content = @plugins.dispatch(:asset_product_extras, product).collect { |content| instance_eval(&content) } %> | |
2 | +<% extra_properties = @plugins.dispatch(:asset_product_properties, product)%> | |
3 | + | |
4 | +<li class="search-product-item <%= 'highlighted' if product.highlighted? %>"> | |
5 | + | |
6 | + <div class="search-product-item-first-column"> | |
7 | + <%= render :partial => 'search/image', :object => product %> | |
8 | + | |
9 | + <% if product.available %> | |
10 | + <% if product.price && product.price > 0 %> | |
11 | + <% has_discount = product.discount && product.discount > 0 %> | |
12 | + <% if product.price %> | |
13 | + <span class="search-product-price-textid"><%=_("from") if has_discount %></span><%= price_span(product.price, :class => "search-product-price " + (has_discount ? 'with-discount' : '')) %> | |
14 | + <% if has_discount %> | |
15 | + <span class="search-product-price-textid"><%=_("by")%></span><%= price_span(product.price_with_discount, :class => "search-product-price") %> | |
16 | + <% end %> | |
17 | + <% if product.unit %> | |
18 | + <span class="search-product-unit"> <%= _('/') %> <%= product.unit.name %></span> | |
19 | + <% end %> | |
20 | + <% end %> | |
21 | + <div class="search-product-inputs-info"> | |
22 | + <% if p = product.percentage_from_solidarity_economy %> | |
23 | + <div class="search-product-percentage-from-solidarity-economy search-product-ecosol-percentage-icon-<%= p[0].to_s %>" | |
24 | + title="<%=_('Percentage of inputs from solidarity economy')%>"> | |
25 | + <%= p[1] %> | |
26 | + </div> | |
27 | + <% end %> | |
28 | + | |
29 | + <% if product.price_described? %> | |
30 | + <% title = (product.inputs.relevant_to_price + product.price_details).map{ |i| | |
31 | + '<div class="search-product-input-dots-to-price">' + | |
32 | + '<div class="search-product-input-name">' + i.name + '</div>' + | |
33 | + price_span(i.price, :class => 'search-product-input-price') + | |
34 | + '</div>' }.join('') %> | |
35 | + <%= link_to_function _("Open Price"), '', :title => title, :class => "search-product-price-details" %> | |
36 | + <% end %> | |
37 | + </div> | |
38 | + <% end %> | |
39 | + <% else %> | |
40 | + <span class="product-not-available"><%= _('Not available') %></div> | |
41 | + <% end %> | |
42 | + | |
43 | + </div> | |
44 | + <div class="search-product-item-second-column"> | |
45 | + <%= link_to_product product, :class => 'search-result-title' %> | |
46 | + <div class="search-product-supplier"> | |
47 | + <span class="search-field-label"><%= _('Supplier') %> </span><%= link_to_homepage(product.enterprise.name, product.enterprise.identifier) %> | |
48 | + </div> | |
49 | + <div class="search-product-description"> | |
50 | + <% if product.description %> | |
51 | + <% desc_stripped = strip_tags(product.description) %> | |
52 | + <span class="search-field-label"><%= _('Description') %> </span><%= excerpt(desc_stripped, desc_stripped.first(3), 300) %> | |
53 | + <% end %> | |
54 | + </div> | |
55 | + </div> | |
56 | + <div class="search-product-item-third-column"> | |
57 | + <div class="search-product-region"> | |
58 | + <% if product.enterprise.region %> | |
59 | + <span class="search-field-label"><%= _('City') %></span> | |
60 | + <br /><%= city_with_state(product.enterprise.region) %> | |
61 | + <% end %> | |
62 | + </div> | |
63 | + <div class="search-product-qualifiers"> | |
64 | + <% if product.product_qualifiers.count > 0 %> | |
65 | + <span class="search-field-label"><%= _('Qualifiers') %></span> | |
66 | + <% product.product_qualifiers.each do |pq| %> | |
67 | + <% if pq.qualifier %> | |
68 | + <span class="search-product-qualifier"><%= pq.qualifier.name + (pq.certifier.nil? ? _(";") : '') %></span> | |
69 | + <% end %> | |
70 | + <% if pq.certifier %> | |
71 | + <span class="search-product-certifier"> <%= _('cert. ') + pq.certifier.name + _(";") %></span> | |
72 | + <% end %> | |
73 | + <% end %> | |
74 | + <% end %> | |
75 | + </div> | |
76 | + </div> | |
77 | + | |
78 | + <div style="clear: both"></div> | |
79 | + | |
80 | + <%= extra_content.join('\n') %> | |
81 | + <% extra_properties.each do |property| %> | |
82 | + <div><%= property[:name] + ': ' + instance_eval(&property[:content]) %></div> | |
83 | + <% end %> | |
84 | + | |
85 | +</li> | ... | ... |
... | ... | @@ -0,0 +1,13 @@ |
1 | +<li class="search-text-article-item article-item"> | |
2 | + <%= link_to(text_article.title, text_article.url, :class => "search-result-title") %> | |
3 | + | |
4 | + <div class="search-content-first-column"> | |
5 | + <%= render :partial => 'image', :object => text_article %> | |
6 | + </div> | |
7 | + <table class="noborder search-content-second-column"> | |
8 | + <%= render :partial => 'article_common', :object => text_article %> | |
9 | + </table> | |
10 | + <%= render :partial => 'article_last_change', :object => text_article %> | |
11 | + | |
12 | + <div style="clear: both"></div> | |
13 | +</li> | ... | ... |
... | ... | @@ -0,0 +1,25 @@ |
1 | +<li class="search-uploaded-file-item article-item"> | |
2 | + <%= link_to uploaded_file.filename, uploaded_file.view_url, :class => 'search-result-title' %> | |
3 | + | |
4 | + <div class="search-content-first-column"> | |
5 | + <%= render :partial => 'image', :object => uploaded_file %> | |
6 | + </div> | |
7 | + | |
8 | + <table class="noborder search-content-second-column"> | |
9 | + <%= render :partial => 'article_author', :object => uploaded_file %> | |
10 | + <%= render :partial => 'article_description', :object => uploaded_file %> | |
11 | + | |
12 | + <% if uploaded_file.parent and uploaded_file.parent.published? %> | |
13 | + <tr class="search-uploaded-file-parent"> | |
14 | + <td class="search-field-label"><%= uploaded_file.parent.gallery? ? _("Gallery") : _("Folder") %></td> | |
15 | + <td><%= link_to uploaded_file.parent.name, uploaded_file.parent.url %></td> | |
16 | + </tr> | |
17 | + <% end %> | |
18 | + | |
19 | + <%= render :partial => 'article_tags', :object => uploaded_file.tags %> | |
20 | + <%= render :partial => 'article_categories', :object => uploaded_file.categories %> | |
21 | + </table> | |
22 | + <%= render :partial => 'article_last_change', :object => uploaded_file %> | |
23 | + | |
24 | + <div style="clear:both"></div> | |
25 | +</li> | ... | ... |