Commit 1890177fe10176810f348453e1629352af2af04f

Authored by Victor Costa
2 parents 7da8bc84 a7ef8536

Merge branch 'master' into AI3220_proposals

Showing 798 changed files with 89572 additions and 136888 deletions   Show diff stats

Too many changes.

To preserve performance only 100 of 798 files displayed.

1 --ignore-dir=log 1 --ignore-dir=log
2 --ignore-dir=tmp 2 --ignore-dir=tmp
3 --ignore-dir=pkg 3 --ignore-dir=pkg
  4 +--ignore-dir=public/javascripts/cache
  5 +--ignore-dir=public/stylesheets/cache
@@ -41,6 +41,7 @@ Alessandro Palmeira + Paulo Meirelles <alessandro.palmeira@gmail.com> @@ -41,6 +41,7 @@ Alessandro Palmeira + Paulo Meirelles <alessandro.palmeira@gmail.com>
41 Alessandro Palmeira + Paulo Meirelles + João M. M. da Silva <alessandro.palmeira@gmail.com> 41 Alessandro Palmeira + Paulo Meirelles + João M. M. da Silva <alessandro.palmeira@gmail.com>
42 Alessandro Palmeira + Rafael Manzo <alessandro.palmeira@gmail.com> 42 Alessandro Palmeira + Rafael Manzo <alessandro.palmeira@gmail.com>
43 Ana Losnak <analosnak@gmail.com> 43 Ana Losnak <analosnak@gmail.com>
  44 +Andre Bernardes <andrebsguedes@gmail.com>
44 Antonio Terceiro + Carlos Morais <terceiro@colivre.coop.br> 45 Antonio Terceiro + Carlos Morais <terceiro@colivre.coop.br>
45 Antonio Terceiro + Paulo Meirelles <terceiro@colivre.coop.br> 46 Antonio Terceiro + Paulo Meirelles <terceiro@colivre.coop.br>
46 Antonio Terceiro <terceiro@colivre.coop.br> 47 Antonio Terceiro <terceiro@colivre.coop.br>
@@ -132,6 +133,7 @@ Francisco Marcelo de Araújo Lima Júnior &lt;maljunior@gmail.com&gt; @@ -132,6 +133,7 @@ Francisco Marcelo de Araújo Lima Júnior &lt;maljunior@gmail.com&gt;
132 Gabriela Navarro <navarro1703@gmail.com> 133 Gabriela Navarro <navarro1703@gmail.com>
133 Grazieno Pellegrino <grazieno@gmail.com> 134 Grazieno Pellegrino <grazieno@gmail.com>
134 Gust <darksshades@hotmail.com> 135 Gust <darksshades@hotmail.com>
  136 +Hebert Douglas <hebertdougl@gmail.com>
135 Hugo Melo <hugo@riseup.net> 137 Hugo Melo <hugo@riseup.net>
136 Isaac Canan <isaac@intelletto.com.br> 138 Isaac Canan <isaac@intelletto.com.br>
137 Italo Valcy <italo@dcc.ufba.br> 139 Italo Valcy <italo@dcc.ufba.br>
@@ -196,6 +198,7 @@ Martín Olivera &lt;molivera@solar.org.ar&gt; @@ -196,6 +198,7 @@ Martín Olivera &lt;molivera@solar.org.ar&gt;
196 Moises Machado <moises@colivre.coop.br> 198 Moises Machado <moises@colivre.coop.br>
197 Naíla Alves <naila@colivre.coop.br> 199 Naíla Alves <naila@colivre.coop.br>
198 Nanda Lopes <nanda.listas+psl@gmail.com> 200 Nanda Lopes <nanda.listas+psl@gmail.com>
  201 +Parley Martins <parleypachecomartins@gmail.com>
199 Paulo Meirelles + Alessandro Palmeira + João M. M. da Silva <paulo@softwarelivre.org> 202 Paulo Meirelles + Alessandro Palmeira + João M. M. da Silva <paulo@softwarelivre.org>
200 Paulo Meirelles + Alessandro Palmeira <paulo@softwarelivre.org> 203 Paulo Meirelles + Alessandro Palmeira <paulo@softwarelivre.org>
201 Paulo Meirelles + Carlos Morais <paulo@softwarelivre.org> 204 Paulo Meirelles + Carlos Morais <paulo@softwarelivre.org>
@@ -230,6 +233,8 @@ Rodrigo Souto &lt;rodrigo@colivre.coop.br&gt; @@ -230,6 +233,8 @@ Rodrigo Souto &lt;rodrigo@colivre.coop.br&gt;
230 Ronny Kursawe <kursawe.ronny@googlemail.com> 233 Ronny Kursawe <kursawe.ronny@googlemail.com>
231 root <root@debian.sdr.serpro> 234 root <root@debian.sdr.serpro>
232 Samuel R. C. Vale <srcvale@holoscopio.com> 235 Samuel R. C. Vale <srcvale@holoscopio.com>
  236 +Tallys Martins <tallysmartins@gmail.com>
  237 +tallys <tallys@tallys.(none)>
233 Valessio Brito <contato@valessiobrito.com.br> 238 Valessio Brito <contato@valessiobrito.com.br>
234 Valessio Brito <contato@valessiobrito.info> 239 Valessio Brito <contato@valessiobrito.info>
235 Valessio Brito <valessio@gmail.com> 240 Valessio Brito <valessio@gmail.com>
1 source "https://rubygems.org" 1 source "https://rubygems.org"
2 -gem 'rails'  
3 -gem 'fast_gettext'  
4 -gem 'acts-as-taggable-on'  
5 -gem 'prototype-rails'  
6 -gem 'prototype_legacy_helper', '0.0.0', :path => 'vendor/prototype_legacy_helper'  
7 -gem 'rails_autolink'  
8 -gem 'pg'  
9 -gem 'rmagick'  
10 -gem 'RedCloth'  
11 -gem 'will_paginate'  
12 -gem 'ruby-feedparser'  
13 -gem 'daemons'  
14 -gem 'thin'  
15 -gem 'hpricot'  
16 -gem 'nokogiri' 2 +gem 'rails', '~> 3.2.19'
  3 +gem 'fast_gettext', '~> 0.6.8'
  4 +gem 'acts-as-taggable-on', '~> 3.0.2'
  5 +gem 'prototype-rails', '~> 3.2.1'
  6 +gem 'prototype_legacy_helper', '0.0.0', :path => 'vendor/prototype_legacy_helper'
  7 +gem 'rails_autolink', '~> 1.1.5'
  8 +gem 'pg', '~> 0.13.2'
  9 +gem 'rmagick', '~> 2.13.1'
  10 +gem 'RedCloth', '~> 4.2.9'
  11 +gem 'will_paginate', '~> 3.0.3'
  12 +gem 'ruby-feedparser', '~> 0.7'
  13 +gem 'daemons', '~> 1.1.5'
  14 +gem 'thin', '~> 1.3.1'
  15 +gem 'hpricot', '~> 0.8.6'
  16 +gem 'nokogiri', '~> 1.5.5'
17 gem 'rake', :require => false 17 gem 'rake', :require => false
18 -gem 'rest-client'  
19 -gem 'exception_notification' 18 +gem 'rest-client', '~> 1.6.7'
  19 +gem 'exception_notification', '~> 4.0.1'
  20 +gem 'gettext', '~> 2.2.1', :require => false, :group => :development
  21 +gem 'locale', '~> 2.0.5'
20 22
21 # FIXME list here all actual dependencies (i.e. the ones in debian/control), 23 # FIXME list here all actual dependencies (i.e. the ones in debian/control),
22 # with their GEM names (not the Debian package names) 24 # with their GEM names (not the Debian package names)
23 25
24 group :production do 26 group :production do
25 - gem 'dalli' 27 + gem 'dalli', '~> 2.7.0'
26 end 28 end
27 29
28 group :test do 30 group :test do
29 - gem 'rspec'  
30 - gem 'rspec-rails'  
31 - gem 'mocha', :require => false 31 + gem 'rspec', '~> 2.10.0'
  32 + gem 'rspec-rails', '~> 2.10.1'
  33 + gem 'mocha', '~> 1.1.0', :require => false
32 end 34 end
33 35
34 group :cucumber do 36 group :cucumber do
35 - gem 'cucumber-rails', :require => false  
36 - gem 'capybara'  
37 - gem 'cucumber'  
38 - gem 'database_cleaner'  
39 - gem 'selenium-webdriver' 37 + gem 'cucumber-rails', '~> 1.0.6', :require => false
  38 + gem 'capybara', '~> 2.1.0'
  39 + gem 'cucumber', '~> 1.0.6'
  40 + gem 'database_cleaner', '~> 1.2.0'
  41 + gem 'selenium-webdriver', '~> 2.39.0'
40 end 42 end
41 43
42 -# include plugin gemfiles  
43 -Dir.glob(File.join('config', 'plugins', '*')).each do |plugin|  
44 - plugin_gemfile = File.join(plugin, 'Gemfile')  
45 - eval File.read(plugin_gemfile) if File.exists?(plugin_gemfile) 44 +# include gemfiles from enabled plugins
  45 +# plugins in baseplugins/ are not included on purpose. They should not have any
  46 +# dependencies.
  47 +Dir.glob('config/plugins/*/Gemfile').each do |gemfile|
  48 + eval File.read(gemfile)
46 end 49 end
Gemfile.lock
@@ -1,191 +0,0 @@ @@ -1,191 +0,0 @@
1 -PATH  
2 - remote: vendor/prototype_legacy_helper  
3 - specs:  
4 - prototype_legacy_helper (0.0.0)  
5 -  
6 -GEM  
7 - remote: https://rubygems.org/  
8 - specs:  
9 - RedCloth (4.2.9)  
10 - actionmailer (3.2.6)  
11 - actionpack (= 3.2.6)  
12 - mail (~> 2.4.4)  
13 - actionpack (3.2.6)  
14 - activemodel (= 3.2.6)  
15 - activesupport (= 3.2.6)  
16 - builder (~> 3.0.0)  
17 - erubis (~> 2.7.0)  
18 - journey (~> 1.0.1)  
19 - rack (~> 1.4.0)  
20 - rack-cache (~> 1.2)  
21 - rack-test (~> 0.6.1)  
22 - sprockets (~> 2.1.3)  
23 - activemodel (3.2.6)  
24 - activesupport (= 3.2.6)  
25 - builder (~> 3.0.0)  
26 - activerecord (3.2.6)  
27 - activemodel (= 3.2.6)  
28 - activesupport (= 3.2.6)  
29 - arel (~> 3.0.2)  
30 - tzinfo (~> 0.3.29)  
31 - activeresource (3.2.6)  
32 - activemodel (= 3.2.6)  
33 - activesupport (= 3.2.6)  
34 - activesupport (3.2.6)  
35 - i18n (~> 0.6)  
36 - multi_json (~> 1.0)  
37 - acts-as-taggable-on (3.0.2)  
38 - rails (>= 3, < 5)  
39 - arel (3.0.2)  
40 - builder (3.0.0)  
41 - capybara (2.1.0)  
42 - mime-types (>= 1.16)  
43 - nokogiri (>= 1.3.3)  
44 - rack (>= 1.0.0)  
45 - rack-test (>= 0.5.4)  
46 - xpath (~> 2.0)  
47 - childprocess (0.3.3)  
48 - ffi (~> 1.0.6)  
49 - cucumber (1.0.6)  
50 - builder (>= 2.1.2)  
51 - diff-lcs (>= 1.1.2)  
52 - gherkin (~> 2.4.18)  
53 - json (>= 1.4.6)  
54 - term-ansicolor (>= 1.0.6)  
55 - cucumber-rails (1.0.6)  
56 - capybara (>= 1.1.1)  
57 - cucumber (>= 1.0.6)  
58 - nokogiri (>= 1.5.0)  
59 - daemons (1.1.5)  
60 - dalli (2.7.0)  
61 - database_cleaner (1.2.0)  
62 - diff-lcs (1.1.3)  
63 - erubis (2.7.0)  
64 - eventmachine (0.12.10)  
65 - exception_notification (4.0.1)  
66 - actionmailer (>= 3.0.4)  
67 - activesupport (>= 3.0.4)  
68 - fast_gettext (0.6.8)  
69 - ffi (1.0.11)  
70 - gherkin (2.4.21)  
71 - json (>= 1.4.6)  
72 - hike (1.2.1)  
73 - hpricot (0.8.6)  
74 - i18n (0.6.0)  
75 - journey (1.0.3)  
76 - json (1.7.3)  
77 - mail (2.4.4)  
78 - i18n (>= 0.4.0)  
79 - mime-types (~> 1.16)  
80 - treetop (~> 1.4.8)  
81 - metaclass (0.0.1)  
82 - mime-types (1.19)  
83 - mocha (0.11.3)  
84 - metaclass (~> 0.0.1)  
85 - multi_json (1.3.6)  
86 - nokogiri (1.5.5)  
87 - pg (0.13.2)  
88 - polyglot (0.3.3)  
89 - prototype-rails (3.2.1)  
90 - rails (~> 3.2)  
91 - rack (1.4.1)  
92 - rack-cache (1.2)  
93 - rack (>= 0.4)  
94 - rack-ssl (1.3.2)  
95 - rack  
96 - rack-test (0.6.1)  
97 - rack (>= 1.0)  
98 - rails (3.2.6)  
99 - actionmailer (= 3.2.6)  
100 - actionpack (= 3.2.6)  
101 - activerecord (= 3.2.6)  
102 - activeresource (= 3.2.6)  
103 - activesupport (= 3.2.6)  
104 - bundler (~> 1.0)  
105 - railties (= 3.2.6)  
106 - rails_autolink (1.1.5)  
107 - rails (> 3.1)  
108 - railties (3.2.6)  
109 - actionpack (= 3.2.6)  
110 - activesupport (= 3.2.6)  
111 - rack-ssl (~> 1.3.2)  
112 - rake (>= 0.8.7)  
113 - rdoc (~> 3.4)  
114 - thor (>= 0.14.6, < 2.0)  
115 - rake (0.9.2.2)  
116 - rdoc (3.9.4)  
117 - rest-client (1.6.7)  
118 - mime-types (>= 1.16)  
119 - rmagick (2.13.1)  
120 - rspec (2.10.0)  
121 - rspec-core (~> 2.10.0)  
122 - rspec-expectations (~> 2.10.0)  
123 - rspec-mocks (~> 2.10.0)  
124 - rspec-core (2.10.1)  
125 - rspec-expectations (2.10.0)  
126 - diff-lcs (~> 1.1.3)  
127 - rspec-mocks (2.10.1)  
128 - rspec-rails (2.10.1)  
129 - actionpack (>= 3.0)  
130 - activesupport (>= 3.0)  
131 - railties (>= 3.0)  
132 - rspec (~> 2.10.0)  
133 - ruby-feedparser (0.7)  
134 - rubyzip (1.1.2)  
135 - selenium-webdriver (2.39.0)  
136 - childprocess (>= 0.2.5)  
137 - multi_json (~> 1.0)  
138 - rubyzip (~> 1.0)  
139 - websocket (~> 1.0.4)  
140 - sprockets (2.1.3)  
141 - hike (~> 1.2)  
142 - multi_json (~> 1.0)  
143 - rack (~> 1.0)  
144 - tilt (~> 1.1, != 1.3.0)  
145 - term-ansicolor (1.0.7)  
146 - thin (1.3.1)  
147 - daemons (>= 1.0.9)  
148 - eventmachine (>= 0.12.6)  
149 - rack (>= 1.0.0)  
150 - thor (0.15.3)  
151 - tilt (1.3.3)  
152 - treetop (1.4.10)  
153 - polyglot  
154 - polyglot (>= 0.3.1)  
155 - tzinfo (0.3.33)  
156 - websocket (1.0.7)  
157 - will_paginate (3.0.3)  
158 - xpath (2.0.0)  
159 - nokogiri (~> 1.3)  
160 -  
161 -PLATFORMS  
162 - ruby  
163 -  
164 -DEPENDENCIES  
165 - RedCloth  
166 - acts-as-taggable-on  
167 - capybara  
168 - cucumber  
169 - cucumber-rails  
170 - daemons  
171 - dalli  
172 - database_cleaner  
173 - exception_notification  
174 - fast_gettext  
175 - hpricot  
176 - mocha  
177 - nokogiri  
178 - pg  
179 - prototype-rails  
180 - prototype_legacy_helper (= 0.0.0)!  
181 - rails  
182 - rails_autolink  
183 - rake  
184 - rest-client  
185 - rmagick  
186 - rspec  
187 - rspec-rails  
188 - ruby-feedparser  
189 - selenium-webdriver  
190 - thin  
191 - will_paginate  
@@ -186,8 +186,8 @@ Apache instalation @@ -186,8 +186,8 @@ Apache instalation
186 186
187 # apt-get install apache2 187 # apt-get install apache2
188 188
189 -Apache configuration  
190 --------------------- 189 +Configuration - noosfero at /
  190 +-----------------------------
191 191
192 First you have to enable the following some apache modules: 192 First you have to enable the following some apache modules:
193 193
@@ -257,6 +257,62 @@ Now restart your apache server (as root): @@ -257,6 +257,62 @@ Now restart your apache server (as root):
257 257
258 # invoke-rc.d apache2 restart 258 # invoke-rc.d apache2 restart
259 259
  260 +Configuration - noosfero at a /subdirectory
  261 +-------------------------------------------
  262 +
  263 +This section describes how to configure noosfero at a subdirectory, what is
  264 +specially useful when you want Noosfero to share a domain name with other
  265 +applications. For example you can host noosfero at yourdomain.com/social, a
  266 +webmail application at yourdomain.com/webmail, and have a static HTML website
  267 +at yourdomain.com/.
  268 +
  269 +**NOTE:** Some plugins might not work well with this setting. Before deploying
  270 +this setting, make sure you test that everything you need works properly with
  271 +it.
  272 +
  273 +The configuration is similar to the main configuration instructions, except for
  274 +the following points. In the description below, replace '/subdirectory' with
  275 +the actual subdirectory you want.
  276 +
  277 +1) add a `prefix: /subdirectory` line to your thin configuration file (thin.yml).
  278 +
  279 +1.1) remember to restart the noosfero application server whenever you make
  280 +changes to that configuration file.
  281 +
  282 + # service noosfero restart
  283 +
  284 +2) add a line saying `export RAILS_RELATIVE_URL_ROOT=/subdirectory` to
  285 +/etc/default/noosfero (you can create it with just this line if it does not
  286 +exist already).
  287 +
  288 +3) You should add the following apache configuration to an existing virtual
  289 +host (plus the `<Proxy balancer://noosfero>` section as displayed above):
  290 +
  291 +```
  292 +Alias /subdirectory /path/to/noosfero/public
  293 +<Directory "/path/to/noosfero/public">
  294 + Options FollowSymLinks
  295 + AllowOverride None
  296 + Order Allow,Deny
  297 + Allow from all
  298 +
  299 + Include /path/to/noosfero/etc/noosfero/apache/cache.conf
  300 +
  301 + RewriteEngine On
  302 + RewriteBase /subdirectory
  303 + # Rewrite index to check for static index.html
  304 + RewriteRule ^$ index.html [QSA]
  305 + # Rewrite to check for Rails cached page
  306 + RewriteRule ^([^.]+)$ $1.html [QSA]
  307 + RewriteCond %{REQUEST_FILENAME} !-f
  308 + RewriteRule ^(.*)$ http://localhost:3000%{REQUEST_URI} [P,QSA,L]
  309 +</Directory>
  310 +```
  311 +
  312 +3.1) remember to reload the apache server whenever any apache configuration
  313 +file changes.
  314 +
  315 + # sudo service apache2 reload
260 316
261 Enabling exception notifications 317 Enabling exception notifications
262 ================================ 318 ================================
@@ -6,3 +6,13 @@ @@ -6,3 +6,13 @@
6 require File.expand_path('../config/application', __FILE__) 6 require File.expand_path('../config/application', __FILE__)
7 7
8 Noosfero::Application.load_tasks 8 Noosfero::Application.load_tasks
  9 +
  10 +[
  11 + "baseplugins/*/{tasks,lib/tasks,rails/tasks}/**/*.rake",
  12 + "config/plugins/*/{tasks,lib/tasks,rails/tasks}/**/*.rake",
  13 + "config/plugins/*/vendor/plugins/*/{tasks,lib/tasks,rails/tasks}/**/*.rake",
  14 +].map do |pattern|
  15 + Dir.glob(pattern).sort
  16 +end.flatten.each do |taskfile|
  17 + load taskfile
  18 +end
@@ -3,7 +3,7 @@ @@ -3,7 +3,7 @@
3 3
4 VAGRANTFILE_API_VERSION = "2" 4 VAGRANTFILE_API_VERSION = "2"
5 Vagrant.configure(VAGRANTFILE_API_VERSION) do |config| 5 Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
6 - config.vm.box = "debian-wheezy" 6 + config.vm.box = ENV.fetch('VAGRANT_BOX', "debian-wheezy")
7 config.vm.network :forwarded_port, host: 3000, guest: 3000 7 config.vm.network :forwarded_port, host: 3000, guest: 3000
8 config.vm.provision :shell do |shell| 8 config.vm.provision :shell do |shell|
9 shell.inline = 'su vagrant -c /vagrant/script/vagrant' 9 shell.inline = 'su vagrant -c /vagrant/script/vagrant'
app/controllers/application_controller.rb
@@ -8,7 +8,7 @@ class ApplicationController &lt; ActionController::Base @@ -8,7 +8,7 @@ class ApplicationController &lt; ActionController::Base
8 before_filter :init_noosfero_plugins 8 before_filter :init_noosfero_plugins
9 before_filter :allow_cross_domain_access 9 before_filter :allow_cross_domain_access
10 before_filter :login_required, :if => :private_environment? 10 before_filter :login_required, :if => :private_environment?
11 - before_filter :verify_members_whitelist, :if => :user 11 + before_filter :verify_members_whitelist, :if => [:private_environment?, :user]
12 12
13 def verify_members_whitelist 13 def verify_members_whitelist
14 render_access_denied unless user.is_admin? || environment.in_whitelist?(user) 14 render_access_denied unless user.is_admin? || environment.in_whitelist?(user)
@@ -40,7 +40,7 @@ class ApplicationController &lt; ActionController::Base @@ -40,7 +40,7 @@ class ApplicationController &lt; ActionController::Base
40 40
41 theme_layout = theme_option(:layout) 41 theme_layout = theme_option(:layout)
42 if theme_layout 42 if theme_layout
43 - theme_view_file('layouts/'+theme_layout) || theme_layout 43 + (theme_view_file('layouts/'+theme_layout) || theme_layout).to_s
44 else 44 else
45 'application' 45 'application'
46 end 46 end
app/controllers/my_profile/cms_controller.rb
@@ -227,7 +227,7 @@ class CmsController &lt; MyProfileController @@ -227,7 +227,7 @@ class CmsController &lt; MyProfileController
227 @article = profile.articles.find(params[:id]) 227 @article = profile.articles.find(params[:id])
228 if request.post? 228 if request.post?
229 @article.destroy 229 @article.destroy
230 - session[:notice] = _("\"#{@article.name}\" was removed.") 230 + session[:notice] = _("\"%s\" was removed." % @article.name)
231 referer = Rails.application.routes.recognize_path URI.parse(request.referer).path rescue nil 231 referer = Rails.application.routes.recognize_path URI.parse(request.referer).path rescue nil
232 if referer and referer[:controller] == 'cms' and referer[:action] != 'edit' 232 if referer and referer[:controller] == 'cms' and referer[:action] != 'edit'
233 redirect_to referer 233 redirect_to referer
app/controllers/my_profile/friends_controller.rb 100644 → 100755
@@ -20,7 +20,7 @@ class FriendsController &lt; MyProfileController @@ -20,7 +20,7 @@ class FriendsController &lt; MyProfileController
20 20
21 class << self 21 class << self
22 def per_page 22 def per_page
23 - 10 23 + 12
24 end 24 end
25 end 25 end
26 def per_page 26 def per_page
app/controllers/public/account_controller.rb
@@ -97,6 +97,7 @@ class AccountController &lt; ApplicationController @@ -97,6 +97,7 @@ class AccountController &lt; ApplicationController
97 @user.return_to = session[:return_to] 97 @user.return_to = session[:return_to]
98 @person = Person.new(params[:profile_data]) 98 @person = Person.new(params[:profile_data])
99 @person.environment = @user.environment 99 @person.environment = @user.environment
  100 +
100 if request.post? 101 if request.post?
101 if may_be_a_bot 102 if may_be_a_bot
102 set_signup_start_time_for_now 103 set_signup_start_time_for_now
@@ -115,6 +116,14 @@ class AccountController &lt; ApplicationController @@ -115,6 +116,14 @@ class AccountController &lt; ApplicationController
115 invitation.update_attributes!({:friend => @user.person}) 116 invitation.update_attributes!({:friend => @user.person})
116 invitation.finish 117 invitation.finish
117 end 118 end
  119 +
  120 + unless params[:file].nil?
  121 + image = Image::new :uploaded_data=> params[:file][:image]
  122 +
  123 + @user.person.image = image
  124 + @user.person.save
  125 + end
  126 +
118 if @user.activated? 127 if @user.activated?
119 self.current_user = @user 128 self.current_user = @user
120 check_join_in_community(@user) 129 check_join_in_community(@user)
@@ -184,7 +193,7 @@ class AccountController &lt; ApplicationController @@ -184,7 +193,7 @@ class AccountController &lt; ApplicationController
184 else 193 else
185 @change_password.errors[:base] << _('Could not find any user with %s equal to "%s".') % [fields_label, params[:value]] 194 @change_password.errors[:base] << _('Could not find any user with %s equal to "%s".') % [fields_label, params[:value]]
186 end 195 end
187 - rescue ActiveRecord::RecordInvald 196 + rescue ActiveRecord::RecordInvalid
188 @change_password.errors[:base] << _('Could not perform password recovery for the user.') 197 @change_password.errors[:base] << _('Could not perform password recovery for the user.')
189 end 198 end
190 end 199 end
app/controllers/public/chat_controller.rb
@@ -19,9 +19,13 @@ class ChatController &lt; PublicController @@ -19,9 +19,13 @@ class ChatController &lt; PublicController
19 def avatar 19 def avatar
20 profile = environment.profiles.find_by_identifier(params[:id]) 20 profile = environment.profiles.find_by_identifier(params[:id])
21 filename, mimetype = profile_icon(profile, :minor, true) 21 filename, mimetype = profile_icon(profile, :minor, true)
22 - data = File.read(File.join(Rails.root, 'public', filename))  
23 - render :text => data, :layout => false, :content_type => mimetype  
24 - expires_in 24.hours 22 + if filename =~ /^https?:/
  23 + redirect_to filename
  24 + else
  25 + data = File.read(File.join(Rails.root, 'public', filename))
  26 + render :text => data, :layout => false, :content_type => mimetype
  27 + expires_in 24.hours
  28 + end
25 end 29 end
26 30
27 def index 31 def index
app/controllers/public/content_viewer_controller.rb
@@ -126,7 +126,7 @@ class ContentViewerController &lt; ApplicationController @@ -126,7 +126,7 @@ class ContentViewerController &lt; ApplicationController
126 elsif !@page.display_to?(user) 126 elsif !@page.display_to?(user)
127 if !profile.public? 127 if !profile.public?
128 private_profile_partial_parameters 128 private_profile_partial_parameters
129 - render :template => 'profile/_private_profile', :status => 403 129 + render :template => 'profile/_private_profile', :status => 403, :formats => [:html]
130 allowed = false 130 allowed = false
131 else #if !profile.visible? 131 else #if !profile.visible?
132 render_access_denied 132 render_access_denied
@@ -216,8 +216,6 @@ class ContentViewerController &lt; ApplicationController @@ -216,8 +216,6 @@ class ContentViewerController &lt; ApplicationController
216 if @page.has_posts? 216 if @page.has_posts?
217 posts = get_posts(params[:year], params[:month]) 217 posts = get_posts(params[:year], params[:month])
218 218
219 - posts = posts.includes(:parent, {:profile => [:domains, :environment]}, :author)  
220 -  
221 #FIXME Need to run this before the pagination because this version of 219 #FIXME Need to run this before the pagination because this version of
222 # will_paginate returns a will_paginate collection instead of a 220 # will_paginate returns a will_paginate collection instead of a
223 # relation. 221 # relation.
app/controllers/public/profile_controller.rb
@@ -17,7 +17,11 @@ class ProfileController &lt; PublicController @@ -17,7 +17,11 @@ class ProfileController &lt; PublicController
17 end 17 end
18 @tags = profile.article_tags 18 @tags = profile.article_tags
19 unless profile.display_info_to?(user) 19 unless profile.display_info_to?(user)
20 - profile.visible? ? private_profile : invisible_profile 20 + if profile.visible?
  21 + private_profile
  22 + else
  23 + invisible_profile
  24 + end
21 end 25 end
22 end 26 end
23 27
@@ -315,7 +319,7 @@ class ProfileController &lt; PublicController @@ -315,7 +319,7 @@ class ProfileController &lt; PublicController
315 abuse_report = AbuseReport.new(params[:abuse_report]) 319 abuse_report = AbuseReport.new(params[:abuse_report])
316 if !params[:content_type].blank? 320 if !params[:content_type].blank?
317 article = params[:content_type].constantize.find(params[:content_id]) 321 article = params[:content_type].constantize.find(params[:content_id])
318 - abuse_report.content = instance_eval(&article.reported_version) 322 + abuse_report.content = article_reported_version(article)
319 end 323 end
320 324
321 user.register_report(abuse_report, profile) 325 user.register_report(abuse_report, profile)
@@ -394,6 +398,7 @@ class ProfileController &lt; PublicController @@ -394,6 +398,7 @@ class ProfileController &lt; PublicController
394 398
395 def private_profile 399 def private_profile
396 private_profile_partial_parameters 400 private_profile_partial_parameters
  401 + render :action => 'index', :status => 403
397 end 402 end
398 403
399 def invisible_profile 404 def invisible_profile
app/controllers/public/search_controller.rb
@@ -90,10 +90,14 @@ class SearchController &lt; PublicController @@ -90,10 +90,14 @@ class SearchController &lt; PublicController
90 end 90 end
91 91
92 def events 92 def events
93 - year = (params[:year] ? params[:year].to_i : Date.today.year)  
94 - month = (params[:month] ? params[:month].to_i : Date.today.month)  
95 - day = (params[:day] ? params[:day].to_i : Date.today.day)  
96 - @date = build_date(year, month, day) 93 + if params[:year].blank? && params[:year].blank? && params[:day].blank?
  94 + @date = Date.today
  95 + else
  96 + year = (params[:year] ? params[:year].to_i : Date.today.year)
  97 + month = (params[:month] ? params[:month].to_i : Date.today.month)
  98 + day = (params[:day] ? params[:day].to_i : 1)
  99 + @date = build_date(year, month, day)
  100 + end
97 date_range = (@date - 1.month).at_beginning_of_month..(@date + 1.month).at_end_of_month 101 date_range = (@date - 1.month).at_beginning_of_month..(@date + 1.month).at_end_of_month
98 102
99 @events = [] 103 @events = []
app/helpers/application_helper.rb
@@ -304,7 +304,7 @@ module ApplicationHelper @@ -304,7 +304,7 @@ module ApplicationHelper
304 def partial_for_class(klass, prefix=nil, suffix=nil) 304 def partial_for_class(klass, prefix=nil, suffix=nil)
305 raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' if klass.nil? 305 raise ArgumentError, 'No partial for object. Is there a partial for any class in the inheritance hierarchy?' if klass.nil?
306 name = klass.name.underscore 306 name = klass.name.underscore
307 - controller.view_paths.reverse_each do |view_path| 307 + controller.view_paths.each do |view_path|
308 partial = partial_for_class_in_view_path(klass, view_path, prefix, suffix) 308 partial = partial_for_class_in_view_path(klass, view_path, prefix, suffix)
309 return partial if partial 309 return partial if partial
310 end 310 end
@@ -482,7 +482,12 @@ module ApplicationHelper @@ -482,7 +482,12 @@ module ApplicationHelper
482 '/images/icons-app/enterprise-'+ size.to_s() +'.png' 482 '/images/icons-app/enterprise-'+ size.to_s() +'.png'
483 end 483 end
484 else 484 else
485 - '/images/icons-app/person-'+ size.to_s() +'.png' 485 + pixels = Image.attachment_options[:thumbnails][size].split('x').first
  486 + gravatar_profile_image_url(
  487 + profile.email,
  488 + :size => pixels,
  489 + :d => gravatar_default
  490 + )
486 end 491 end
487 filename = default_or_themed_icon(icon) 492 filename = default_or_themed_icon(icon)
488 end 493 end
@@ -602,7 +607,7 @@ module ApplicationHelper @@ -602,7 +607,7 @@ module ApplicationHelper
602 end 607 end
603 608
604 def gravatar_default 609 def gravatar_default
605 - (respond_to?(:theme_option) && theme_option.present? && theme_option['gravatar']) || NOOSFERO_CONF['gravatar'] 610 + (respond_to?(:theme_option) && theme_option.present? && theme_option['gravatar']) || NOOSFERO_CONF['gravatar'] || 'mm'
606 end 611 end
607 612
608 attr_reader :environment 613 attr_reader :environment
@@ -1281,9 +1286,9 @@ module ApplicationHelper @@ -1281,9 +1286,9 @@ module ApplicationHelper
1281 1286
1282 def delete_article_message(article) 1287 def delete_article_message(article)
1283 if article.folder? 1288 if article.folder?
1284 - _("Are you sure that you want to remove the folder \"#{article.name}\"? Note that all the items inside it will also be removed!") 1289 + _("Are you sure that you want to remove the folder \"%s\"? Note that all the items inside it will also be removed!") % article.name
1285 else 1290 else
1286 - _("Are you sure that you want to remove the item \"#{article.name}\"?") 1291 + _("Are you sure that you want to remove the item \"%s\"?") % article.name
1287 end 1292 end
1288 end 1293 end
1289 1294
@@ -1372,7 +1377,7 @@ module ApplicationHelper @@ -1372,7 +1377,7 @@ module ApplicationHelper
1372 # are old things that do not support it we are keeping this hot spot. 1377 # are old things that do not support it we are keeping this hot spot.
1373 html = @plugins.pipeline(:parse_content, html, source).first 1378 html = @plugins.pipeline(:parse_content, html, source).first
1374 end 1379 end
1375 - html 1380 + html && html.html_safe
1376 end 1381 end
1377 1382
1378 def convert_macro(html, source) 1383 def convert_macro(html, source)
app/helpers/article_helper.rb
@@ -3,6 +3,12 @@ module ArticleHelper @@ -3,6 +3,12 @@ module ArticleHelper
3 include PrototypeHelper 3 include PrototypeHelper
4 include TokenHelper 4 include TokenHelper
5 5
  6 + def article_reported_version(article)
  7 + search_path = Rails.root.join('app', 'views', 'shared', 'reported_versions')
  8 + partial_path = File.join('shared', 'reported_versions', 'profile', partial_for_class_in_view_path(article.class, search_path))
  9 + render_to_string(:partial => partial_path, :locals => {:article => article})
  10 + end
  11 +
6 def custom_options_for_article(article, tokenized_children) 12 def custom_options_for_article(article, tokenized_children)
7 @article = article 13 @article = article
8 14
app/helpers/profile_helper.rb
1 module ProfileHelper 1 module ProfileHelper
2 2
3 - def display_field(title, profile, field, force = false) 3 + COMMON_CATEGORIES = ActiveSupport::OrderedHash.new
  4 + COMMON_CATEGORIES[:content] = [:blogs, :image_galleries, :events, :article_tags]
  5 + COMMON_CATEGORIES[:interests] = [:interests]
  6 + COMMON_CATEGORIES[:general] = nil
  7 +
  8 + PERSON_CATEGORIES = ActiveSupport::OrderedHash.new
  9 + PERSON_CATEGORIES[:basic_information] = [:nickname, :sex, :birth_date, :location, :privacy_setting, :created_at]
  10 + PERSON_CATEGORIES[:contact] = [:contact_phone, :cell_phone, :comercial_phone, :contact_information, :email, :personal_website, :jabber_id]
  11 + PERSON_CATEGORIES[:location] = [:address, :address_reference, :zip_code, :city, :state, :district, :country, :nationality]
  12 + PERSON_CATEGORIES[:work] = [:organization, :organization_website, :professional_activity]
  13 + PERSON_CATEGORIES[:study] = [:schooling, :formation, :area_of_study]
  14 + PERSON_CATEGORIES[:network] = [:friends, :communities, :enterprises]
  15 + PERSON_CATEGORIES.merge!(COMMON_CATEGORIES)
  16 +
  17 + ORGANIZATION_CATEGORIES = ActiveSupport::OrderedHash.new
  18 + ORGANIZATION_CATEGORIES[:basic_information] = [:display_name, :created_at, :foundation_year, :type, :language, :members_count, :location, :address_reference, :historic_and_current_context, :admins]
  19 + ORGANIZATION_CATEGORIES[:contact] = [:contact_person, :contact_phone, :contact_email, :organization_website, :jabber_id]
  20 + ORGANIZATION_CATEGORIES[:economic] = [:business_name, :acronym, :economic_activity, :legal_form, :products, :activities_short_description, :management_information]
  21 + ORGANIZATION_CATEGORIES.merge!(COMMON_CATEGORIES)
  22 +
  23 + CATEGORY_MAP = ActiveSupport::OrderedHash.new
  24 + CATEGORY_MAP[:person] = PERSON_CATEGORIES
  25 + CATEGORY_MAP[:organization] = ORGANIZATION_CATEGORIES
  26 +
  27 + FORCE = {
  28 + :person => [:privacy_setting],
  29 + :organization => [:privacy_setting, :location],
  30 + }
  31 +
  32 + MULTIPLE = {
  33 + :person => [:blogs, :image_galleries, :interests],
  34 + :organization => [:blogs, :image_galleries, :interests],
  35 + }
  36 +
  37 + CUSTOM_LABELS = {
  38 + :zip_code => _('ZIP code'),
  39 + :email => _('e-Mail'),
  40 + :jabber_id => _('Jabber'),
  41 + :birth_date => _('Date of birth'),
  42 + :created_at => _('Profile created at'),
  43 + :members_count => _('Members'),
  44 + :privacy_setting => _('Privacy setting'),
  45 + :article_tags => _('Tags')
  46 + }
  47 +
  48 + EXCEPTION = {
  49 + :person => [:image, :preferred_domain, :description, :tag_list],
  50 + :organization => [:image, :preferred_domain, :description, :tag_list, :address, :zip_code, :city, :state, :country, :district]
  51 + }
  52 +
  53 + def general_fields
  54 + categorized_fields = CATEGORY_MAP[kind].values.flatten
  55 + profile.class.fields.map(&:to_sym) - categorized_fields - EXCEPTION[kind]
  56 + end
  57 +
  58 + def kind
  59 + if profile.kind_of?(Person)
  60 + :person
  61 + else
  62 + :organization
  63 + end
  64 + end
  65 +
  66 + def title(field, entry = nil)
  67 + return self.send("#{field}_custom_title", entry) if MULTIPLE[kind].include?(field) && entry.present?
  68 + CUSTOM_LABELS[field.to_sym] || _(field.to_s.humanize)
  69 + end
  70 +
  71 + def display_field(field)
  72 + force = FORCE[kind].include?(field)
  73 + multiple = MULTIPLE[kind].include?(field)
4 unless force || profile.may_display_field_to?(field, user) 74 unless force || profile.may_display_field_to?(field, user)
5 return '' 75 return ''
6 end 76 end
7 - value = profile.send(field)  
8 - if !value.blank?  
9 - if block_given?  
10 - value = yield(value)  
11 - end  
12 - content_tag('tr', content_tag('td', title, :class => 'field-name') + content_tag('td', value)) 77 + value = begin profile.send(field) rescue nil end
  78 + return '' if value.blank?
  79 + if value.kind_of?(Hash)
  80 + content = self.send("treat_#{field}", value)
  81 + content_tag('tr', content_tag('td', title(field), :class => 'field-name') + content_tag('td', content))
13 else 82 else
14 - '' 83 + entries = multiple ? value : [] << value
  84 + entries.map do |entry|
  85 + content = self.send("treat_#{field}", entry)
  86 + unless content.blank?
  87 + content_tag('tr', content_tag('td', title(field, entry), :class => 'field-name') + content_tag('td', content))
  88 + end
  89 + end.join("\n")
15 end 90 end
16 end 91 end
17 92
18 - def display_contact(profile)  
19 - fields = []  
20 - fields << display_field(_('Address:'), profile, :address).html_safe  
21 - fields << display_field(_('ZIP code:'), profile, :zip_code).html_safe  
22 - fields << display_field(_('Contact phone:'), profile, :contact_phone).html_safe  
23 - fields << display_field(_('e-Mail:'), profile, :email) { |email| link_to_email(email) }.html_safe  
24 - fields << display_field(_('Personal website:'), profile, :personal_website).html_safe  
25 - fields << display_field(_('Jabber:'), profile, :jabber_id).html_safe  
26 - if fields.reject!(&:blank?).empty?  
27 - ''  
28 - else  
29 - content_tag('tr', content_tag('th', _('Contact'), { :colspan => 2 })) + fields.join.html_safe 93 + def treat_email(email)
  94 + link_to_email(email)
  95 + end
  96 +
  97 + def treat_organization_website(url)
  98 + link_to(url, url)
  99 + end
  100 +
  101 + def treat_sex(gender)
  102 + { 'male' => _('Male'), 'female' => _('Female') }[gender]
  103 + end
  104 +
  105 + def treat_date(date)
  106 + show_date(date.to_date)
  107 + end
  108 + alias :treat_birth_date :treat_date
  109 + alias :treat_created_at :treat_date
  110 +
  111 + def treat_friends(friends)
  112 + link_to friends.count, :controller => 'profile', :action => 'friends'
  113 + end
  114 +
  115 + def treat_communities(communities)
  116 + link_to communities.count, :controller => "profile", :action => 'communities'
  117 + end
  118 +
  119 + def treat_enterprises(enterprises)
  120 + if environment.disabled?('disable_asset_enterprises')
  121 + link_to enterprises.count, :controller => "profile", :action => 'enterprises'
  122 + end
  123 + end
  124 +
  125 + def treat_members_count(count)
  126 + link_to count, :controller => 'profile', :action => 'members'
  127 + end
  128 +
  129 + def treat_products(products)
  130 + if profile.kind_of?(Enterprise) && profile.environment.enabled?('products_for_enterprises')
  131 + link_to _('Products/Services'), :controller => 'catalog', :action => 'index'
30 end 132 end
31 end 133 end
32 134
33 - def display_work_info(profile)  
34 - organization = display_field(_('Organization:'), profile, :organization)  
35 - organization_site = display_field(_('Organization website:'), profile, :organization_website) { |url| link_to(url, url) }  
36 - if organization.blank? && organization_site.blank?  
37 - '' 135 + def treat_admins(admins)
  136 + profile.admins.map { |admin| link_to(admin.short_name, admin.url)}.join(', ')
  137 + end
  138 +
  139 + def treat_blogs(blog)
  140 + link_to(n_('One post', '%{num} posts', blog.posts.published.count) % { :num => blog.posts.published.count }, blog.url)
  141 + end
  142 +
  143 + def treat_image_galleries(gallery)
  144 + link_to(n_('One picture', '%{num} pictures', gallery.images.published.count) % { :num => gallery.images.published.count }, gallery.url)
  145 + end
  146 +
  147 + def treat_events(events)
  148 + link_to events.published.count, :controller => 'events', :action => 'events'
  149 + end
  150 +
  151 + def treat_article_tags(tags)
  152 + tag_cloud @tags, :id, { :action => 'tags' }, :max_size => 18, :min_size => 10
  153 + end
  154 +
  155 + def treat_interests(interest)
  156 + link_to interest.name, :controller => 'search', :action => 'category_index', :category_path => interest.explode_path
  157 + end
  158 +
  159 + def article_custom_title(article)
  160 + article.name
  161 + end
  162 + alias :blogs_custom_title :article_custom_title
  163 + alias :image_galleries_custom_title :article_custom_title
  164 +
  165 + def interests_custom_title(interest)
  166 + ''
  167 + end
  168 +
  169 + def method_missing(method, *args, &block)
  170 + if method.to_s =~ /^treat_(.+)$/
  171 + args[0]
  172 + elsif method.to_s =~ /^display_(.+)$/ && CATEGORY_MAP[kind].has_key?($1.to_sym)
  173 + category = $1.to_sym
  174 + fields = category == :general ? general_fields : CATEGORY_MAP[kind][category]
  175 + contents = []
  176 +
  177 + fields.each do |field|
  178 + contents << display_field(field).html_safe
  179 + end
  180 +
  181 + contents = contents.delete_if(&:blank?)
  182 +
  183 + unless contents.empty?
  184 + content_tag('tr', content_tag('th', title(category), { :colspan => 2 })) + contents.join.html_safe
  185 + else
  186 + ''
  187 + end
38 else 188 else
39 - content_tag('tr', content_tag('th', _('Work'), { :colspan => 2 })) + organization + organization_site 189 + super
40 end 190 end
41 end 191 end
42 192
app/helpers/sweeper_helper.rb
@@ -56,12 +56,12 @@ module SweeperHelper @@ -56,12 +56,12 @@ module SweeperHelper
56 if profile 56 if profile
57 profile.blocks.each {|block| 57 profile.blocks.each {|block|
58 conditions = block.class.expire_on 58 conditions = block.class.expire_on
59 - blocks_to_expire << block unless (conditions[:profile] & causes).empty? 59 + blocks_to_expire << block unless (conditions[:profile] & causes).blank?
60 } 60 }
61 end 61 end
62 environment.blocks.each {|block| 62 environment.blocks.each {|block|
63 conditions = block.class.expire_on 63 conditions = block.class.expire_on
64 - blocks_to_expire << block unless (conditions[:environment] & causes).empty? 64 + blocks_to_expire << block unless (conditions[:environment] & causes).blank?
65 } 65 }
66 66
67 blocks_to_expire.uniq! 67 blocks_to_expire.uniq!
app/helpers/tinymce_helper.rb 0 → 100644
@@ -0,0 +1,51 @@ @@ -0,0 +1,51 @@
  1 +module TinymceHelper
  2 + include MacrosHelper
  3 +
  4 + def tinymce_js
  5 + output = ''
  6 + output += javascript_include_tag 'tinymce/js/tinymce/tinymce.min.js'
  7 + output += javascript_include_tag 'tinymce/js/tinymce/jquery.tinymce.min.js'
  8 + output += javascript_include_tag 'tinymce.js'
  9 + output += include_macro_js_files.to_s
  10 + output
  11 + end
  12 +
  13 + def tinymce_init_js options = {}
  14 + options.merge! :document_base_url => environment.top_url,
  15 + :content_css => "/stylesheets/tinymce.css,#{macro_css_files}",
  16 + :plugins => %w[compat3x advlist autolink lists link image charmap print preview hr anchor pagebreak
  17 + searchreplace wordcount visualblocks visualchars code fullscreen
  18 + insertdatetime media nonbreaking save table contextmenu directionality
  19 + emoticons template paste textcolor colorpicker textpattern],
  20 + :language => tinymce_language
  21 +
  22 + options[:toolbar1] = "insertfile undo redo | copy paste | bold italic underline | styleselect fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image"
  23 + if options[:mode] == 'simple'
  24 + options[:menubar] = false
  25 + else
  26 + options[:menubar] = 'edit insert view tools'
  27 + options[:toolbar2] = 'print preview code media | table'
  28 +
  29 + options[:toolbar2] += ' | macros'
  30 + macros_with_buttons.each do |macro|
  31 + options[:toolbar2] += " #{macro.identifier}"
  32 + end
  33 + end
  34 +
  35 + options[:macros_setup] = macros_with_buttons.map do |macro|
  36 + <<-EOS
  37 + ed.addButton('#{macro.identifier}', {
  38 + title: #{macro_title(macro).to_json},
  39 + onclick: #{generate_macro_config_dialog macro},
  40 + image : '#{macro.configuration[:icon_path]}'
  41 + });
  42 + EOS
  43 + end
  44 +
  45 + #cleanup non tinymce options
  46 + options = options.except :mode
  47 +
  48 + "noosfero.tinymce.init(#{options.to_json})"
  49 + end
  50 +
  51 +end
app/models/article.rb
@@ -157,14 +157,17 @@ class Article &lt; ActiveRecord::Base @@ -157,14 +157,17 @@ class Article &lt; ActiveRecord::Base
157 self.profile 157 self.profile
158 end 158 end
159 159
160 - def self.human_attribute_name(attrib, options = {}) 160 + def self.human_attribute_name_with_customization(attrib, options={})
161 case attrib.to_sym 161 case attrib.to_sym
162 when :name 162 when :name
163 _('Title') 163 _('Title')
164 else 164 else
165 - _(self.superclass.human_attribute_name(attrib)) 165 + _(self.human_attribute_name_without_customization(attrib))
166 end 166 end
167 end 167 end
  168 + class << self
  169 + alias_method_chain :human_attribute_name, :customization
  170 + end
168 171
169 def css_class_list 172 def css_class_list
170 [self.class.name.to_css_class] 173 [self.class.name.to_css_class]
@@ -282,13 +285,6 @@ class Article &lt; ActiveRecord::Base @@ -282,13 +285,6 @@ class Article &lt; ActiveRecord::Base
282 end 285 end
283 end 286 end
284 287
285 - def reported_version(options = {})  
286 - article = self  
287 - search_path = Rails.root.join('app', 'views', 'shared', 'reported_versions')  
288 - partial_path = File.join('shared', 'reported_versions', partial_for_class_in_view_path(article.class, search_path))  
289 - lambda { render_to_string(:partial => partial_path, :locals => {:article => article}) }  
290 - end  
291 -  
292 # returns the data of the article. Must be overriden in each subclass to 288 # returns the data of the article. Must be overriden in each subclass to
293 # provide the correct content for the article. 289 # provide the correct content for the article.
294 def data 290 def data
app/models/block.rb
@@ -192,7 +192,7 @@ class Block &lt; ActiveRecord::Base @@ -192,7 +192,7 @@ class Block &lt; ActiveRecord::Base
192 192
193 # Override in your subclasses. 193 # Override in your subclasses.
194 # Define which events and context should cause the block cache to expire 194 # Define which events and context should cause the block cache to expire
195 - # Possible events are: :article, :profile, :friendship, :category 195 + # Possible events are: :article, :profile, :friendship, :category, :role_assignment
196 # Possible contexts are: :profile, :environment 196 # Possible contexts are: :profile, :environment
197 def self.expire_on 197 def self.expire_on
198 { 198 {
@@ -234,4 +234,9 @@ class Block &lt; ActiveRecord::Base @@ -234,4 +234,9 @@ class Block &lt; ActiveRecord::Base
234 duplicated_block 234 duplicated_block
235 end 235 end
236 236
  237 + def copy_from(block)
  238 + self.settings = block.settings
  239 + self.position = block.position
  240 + end
  241 +
237 end 242 end
app/models/change_password.rb
@@ -2,16 +2,19 @@ class ChangePassword &lt; Task @@ -2,16 +2,19 @@ class ChangePassword &lt; Task
2 2
3 attr_accessor :password, :password_confirmation 3 attr_accessor :password, :password_confirmation
4 4
5 - def self.human_attribute_name(attrib, options = {}) 5 + def self.human_attribute_name_with_customization(attrib, options={})
6 case attrib.to_sym 6 case attrib.to_sym
7 when :password 7 when :password
8 _('Password') 8 _('Password')
9 when :password_confirmation 9 when :password_confirmation
10 _('Password Confirmation') 10 _('Password Confirmation')
11 else 11 else
12 - _(self.superclass.human_attribute_name(attrib)) 12 + _(self.human_attribute_name_without_customization(attrib))
13 end 13 end
14 end 14 end
  15 + class << self
  16 + alias_method_chain :human_attribute_name, :customization
  17 + end
15 18
16 validates_presence_of :requestor 19 validates_presence_of :requestor
17 20
app/models/community.rb
@@ -50,16 +50,6 @@ class Community &lt; Organization @@ -50,16 +50,6 @@ class Community &lt; Organization
50 super + FIELDS 50 super + FIELDS
51 end 51 end
52 52
53 - validate :presence_of_required_fieds  
54 -  
55 - def presence_of_required_fieds  
56 - self.required_fields.each do |field|  
57 - if self.send(field).blank?  
58 - self.errors.add_on_blank(field)  
59 - end  
60 - end  
61 - end  
62 -  
63 def active_fields 53 def active_fields
64 environment ? environment.active_community_fields : [] 54 environment ? environment.active_community_fields : []
65 end 55 end
app/models/enterprise.rb
@@ -59,16 +59,6 @@ class Enterprise &lt; Organization @@ -59,16 +59,6 @@ class Enterprise &lt; Organization
59 super + FIELDS 59 super + FIELDS
60 end 60 end
61 61
62 - validate :presence_of_required_fieds  
63 -  
64 - def presence_of_required_fieds  
65 - self.required_fields.each do |field|  
66 - if self.send(field).blank?  
67 - self.errors.add_on_blank(field)  
68 - end  
69 - end  
70 - end  
71 -  
72 def active_fields 62 def active_fields
73 environment ? environment.active_enterprise_fields : [] 63 environment ? environment.active_enterprise_fields : []
74 end 64 end
app/models/environment.rb
@@ -660,6 +660,7 @@ class Environment &lt; ActiveRecord::Base @@ -660,6 +660,7 @@ class Environment &lt; ActiveRecord::Base
660 url = 'http://' 660 url = 'http://'
661 url << (Noosfero.url_options.key?(:host) ? Noosfero.url_options[:host] : default_hostname) 661 url << (Noosfero.url_options.key?(:host) ? Noosfero.url_options[:host] : default_hostname)
662 url << ':' << Noosfero.url_options[:port].to_s if Noosfero.url_options.key?(:port) 662 url << ':' << Noosfero.url_options[:port].to_s if Noosfero.url_options.key?(:port)
  663 + url << Noosfero.root('')
663 url 664 url
664 end 665 end
665 666
@@ -804,7 +805,7 @@ class Environment &lt; ActiveRecord::Base @@ -804,7 +805,7 @@ class Environment &lt; ActiveRecord::Base
804 end 805 end
805 806
806 def notification_emails 807 def notification_emails
807 - [noreply_email.blank? ? nil : noreply_email].compact + admins.map(&:email) 808 + [contact_email].select(&:present?) + admins.map(&:email)
808 end 809 end
809 810
810 after_create :create_templates 811 after_create :create_templates
app/models/external_feed.rb
@@ -13,6 +13,7 @@ class ExternalFeed &lt; ActiveRecord::Base @@ -13,6 +13,7 @@ class ExternalFeed &lt; ActiveRecord::Base
13 attr_accessible :address, :enabled 13 attr_accessible :address, :enabled
14 14
15 def add_item(title, link, date, content) 15 def add_item(title, link, date, content)
  16 + return if content.blank?
16 doc = Hpricot(content) 17 doc = Hpricot(content)
17 doc.search('*').each do |p| 18 doc.search('*').each do |p|
18 if p.instance_of? Hpricot::Elem 19 if p.instance_of? Hpricot::Elem
@@ -30,6 +31,7 @@ class ExternalFeed &lt; ActiveRecord::Base @@ -30,6 +31,7 @@ class ExternalFeed &lt; ActiveRecord::Base
30 article.source = link 31 article.source = link
31 article.profile = blog.profile 32 article.profile = blog.profile
32 article.parent = blog 33 article.parent = blog
  34 + article.author_name = self.feed_title
33 unless blog.children.exists?(:slug => article.slug) 35 unless blog.children.exists?(:slug => article.slug)
34 article.save! 36 article.save!
35 article.delay.create_activity 37 article.delay.create_activity
app/models/feed_reader_block.rb
@@ -85,8 +85,4 @@ class FeedReaderBlock &lt; Block @@ -85,8 +85,4 @@ class FeedReaderBlock &lt; Block
85 block_title(title) + formatted_feed_content 85 block_title(title) + formatted_feed_content
86 end 86 end
87 87
88 - def editable?  
89 - true  
90 - end  
91 -  
92 end 88 end
app/models/link_list_block.rb
@@ -78,16 +78,17 @@ class LinkListBlock &lt; Block @@ -78,16 +78,17 @@ class LinkListBlock &lt; Block
78 address 78 address
79 end 79 end
80 if add !~ /^[a-z]+:\/\// && add !~ /^\// 80 if add !~ /^[a-z]+:\/\// && add !~ /^\//
81 - 'http://' + add 81 + '//' + add
82 else 82 else
  83 + if root = Noosfero.root
  84 + if !add.starts_with?(root)
  85 + add = root + add
  86 + end
  87 + end
83 add 88 add
84 end 89 end
85 end 90 end
86 91
87 - def editable?  
88 - true  
89 - end  
90 -  
91 def icons_options 92 def icons_options
92 ICONS.map do |i| 93 ICONS.map do |i|
93 "<span title=\"#{i[1]}\" class=\"icon-#{i[0]}\" onclick=\"changeIcon(this, '#{i[0]}')\"></span>".html_safe 94 "<span title=\"#{i[1]}\" class=\"icon-#{i[0]}\" onclick=\"changeIcon(this, '#{i[0]}')\"></span>".html_safe
@@ -100,4 +101,5 @@ class LinkListBlock &lt; Block @@ -100,4 +101,5 @@ class LinkListBlock &lt; Block
100 sanitizer = HTML::WhiteListSanitizer.new 101 sanitizer = HTML::WhiteListSanitizer.new
101 sanitizer.sanitize(text) 102 sanitizer.sanitize(text)
102 end 103 end
  104 +
103 end 105 end
app/models/main_block.rb
@@ -16,10 +16,6 @@ class MainBlock &lt; Block @@ -16,10 +16,6 @@ class MainBlock &lt; Block
16 true 16 true
17 end 17 end
18 18
19 - def editable?  
20 - true  
21 - end  
22 -  
23 def cacheable? 19 def cacheable?
24 false 20 false
25 end 21 end
app/models/organization.rb
@@ -30,6 +30,16 @@ class Organization &lt; Profile @@ -30,6 +30,16 @@ class Organization &lt; Profile
30 30
31 scope :more_popular, :order => 'members_count DESC' 31 scope :more_popular, :order => 'members_count DESC'
32 32
  33 + validate :presence_of_required_fieds, :unless => :is_template
  34 +
  35 + def presence_of_required_fieds
  36 + self.required_fields.each do |field|
  37 + if self.send(field).blank?
  38 + self.errors.add_on_blank(field)
  39 + end
  40 + end
  41 + end
  42 +
33 def validation_methodology 43 def validation_methodology
34 self.validation_info ? self.validation_info.validation_methodology : nil 44 self.validation_info ? self.validation_info.validation_methodology : nil
35 end 45 end
@@ -135,7 +145,11 @@ class Organization &lt; Profile @@ -135,7 +145,11 @@ class Organization &lt; Profile
135 end 145 end
136 146
137 def notification_emails 147 def notification_emails
138 - [contact_email.blank? ? nil : contact_email].compact + admins.map(&:email) 148 + emails = [contact_email].select(&:present?) + admins.map(&:email)
  149 + if emails.empty?
  150 + emails << environment.contact_email
  151 + end
  152 + emails
139 end 153 end
140 154
141 def already_request_membership?(person) 155 def already_request_membership?(person)
app/models/person.rb
@@ -161,7 +161,7 @@ class Person &lt; Profile @@ -161,7 +161,7 @@ class Person &lt; Profile
161 FIELDS 161 FIELDS
162 end 162 end
163 163
164 - validate :presence_of_required_fields 164 + validate :presence_of_required_fields, :unless => :is_template
165 165
166 def presence_of_required_fields 166 def presence_of_required_fields
167 self.required_fields.each do |field| 167 self.required_fields.each do |field|
app/models/profile.rb
@@ -346,16 +346,17 @@ class Profile &lt; ActiveRecord::Base @@ -346,16 +346,17 @@ class Profile &lt; ActiveRecord::Base
346 end 346 end
347 347
348 def copy_blocks_from(profile) 348 def copy_blocks_from(profile)
  349 + template_boxes = profile.boxes.select{|box| box.position}
349 self.boxes.destroy_all 350 self.boxes.destroy_all
350 - profile.boxes.each do |box|  
351 - new_box = Box.new 351 + self.boxes = template_boxes.size.times.map { Box.new }
  352 +
  353 + template_boxes.each_with_index do |box, i|
  354 + new_box = self.boxes[i]
352 new_box.position = box.position 355 new_box.position = box.position
353 - self.boxes << new_box  
354 box.blocks.each do |block| 356 box.blocks.each do |block|
355 new_block = block.class.new(:title => block[:title]) 357 new_block = block.class.new(:title => block[:title])
356 - new_block.settings = block.settings  
357 - new_block.position = block.position  
358 - self.boxes[-1].blocks << new_block 358 + new_block.copy_from(block)
  359 + new_box.blocks << new_block
359 end 360 end
360 end 361 end
361 end 362 end
app/models/profile_image_block.rb
@@ -23,10 +23,6 @@ class ProfileImageBlock &lt; Block @@ -23,10 +23,6 @@ class ProfileImageBlock &lt; Block
23 end 23 end
24 end 24 end
25 25
26 - def editable?  
27 - true  
28 - end  
29 -  
30 def cacheable? 26 def cacheable?
31 false 27 false
32 end 28 end
app/models/profile_info_block.rb
@@ -15,10 +15,6 @@ class ProfileInfoBlock &lt; Block @@ -15,10 +15,6 @@ class ProfileInfoBlock &lt; Block
15 end 15 end
16 end 16 end
17 17
18 - def editable?  
19 - false  
20 - end  
21 -  
22 def cacheable? 18 def cacheable?
23 false 19 false
24 end 20 end
app/models/profile_search_block.rb
@@ -11,8 +11,4 @@ class ProfileSearchBlock &lt; Block @@ -11,8 +11,4 @@ class ProfileSearchBlock &lt; Block
11 end 11 end
12 end 12 end
13 13
14 - def editable?  
15 - true  
16 - end  
17 -  
18 end 14 end
app/models/task.rb
@@ -285,8 +285,9 @@ class Task &lt; ActiveRecord::Base @@ -285,8 +285,9 @@ class Task &lt; ActiveRecord::Base
285 # If 285 # If
286 def send_notification(action) 286 def send_notification(action)
287 if sends_email? 287 if sends_email?
288 - if self.requestor  
289 - TaskMailer.generic_message("task_#{action}", self) 288 + if self.requestor && !self.requestor.notification_emails.empty?
  289 + message = TaskMailer.generic_message("task_#{action}", self)
  290 + message.deliver if message
290 end 291 end
291 end 292 end
292 end 293 end
app/models/user.rb
@@ -16,15 +16,18 @@ class User &lt; ActiveRecord::Base @@ -16,15 +16,18 @@ class User &lt; ActiveRecord::Base
16 end 16 end
17 17
18 # FIXME ugly workaround 18 # FIXME ugly workaround
19 - def self.human_attribute_name(attrib, options={}) 19 + def self.human_attribute_name_with_customization(attrib, options={})
20 case attrib.to_sym 20 case attrib.to_sym
21 when :login 21 when :login
22 return [_('Username'), _('Email')].join(' / ') 22 return [_('Username'), _('Email')].join(' / ')
23 when :email 23 when :email
24 return _('e-Mail') 24 return _('e-Mail')
25 - else _(self.superclass.human_attribute_name(attrib)) 25 + else _(self.human_attribute_name_without_customization(attrib))
26 end 26 end
27 end 27 end
  28 + class << self
  29 + alias_method_chain :human_attribute_name, :customization
  30 + end
28 31
29 before_create do |user| 32 before_create do |user|
30 if user.environment.nil? 33 if user.environment.nil?
app/sweepers/role_assignment_sweeper.rb
@@ -13,20 +13,22 @@ class RoleAssignmentSweeper &lt; ActiveRecord::Observer @@ -13,20 +13,22 @@ class RoleAssignmentSweeper &lt; ActiveRecord::Observer
13 protected 13 protected
14 14
15 def expire_caches(role_assignment) 15 def expire_caches(role_assignment)
16 - expire_cache(role_assignment.accessor)  
17 - expire_cache(role_assignment.resource) if role_assignment.resource.respond_to?(:cache_keys) 16 + expire_cache(role_assignment.accessor) if role_assignment.accessor.kind_of?(Profile)
  17 + expire_cache(role_assignment.resource) if role_assignment.resource.kind_of?(Profile)
18 end 18 end
19 19
20 def expire_cache(profile) 20 def expire_cache(profile)
21 per_page = Noosfero::Constants::PROFILE_PER_PAGE 21 per_page = Noosfero::Constants::PROFILE_PER_PAGE
22 - profile.cache_keys(:per_page => per_page).each { |ck|  
23 - expire_timeout_fragment(ck)  
24 - } 22 +
  23 + profile.cache_keys(:per_page => per_page).each { |ck| expire_timeout_fragment(ck) }
  24 + expire_timeout_fragment(profile.members_cache_key(:per_page => per_page))
25 25
26 profile.blocks_to_expire_cache.each { |block| 26 profile.blocks_to_expire_cache.each { |block|
27 blocks = profile.blocks.select{|b| b.kind_of?(block)} 27 blocks = profile.blocks.select{|b| b.kind_of?(block)}
28 BlockSweeper.expire_blocks(blocks) 28 BlockSweeper.expire_blocks(blocks)
29 } 29 }
  30 +
  31 + expire_blocks_cache(profile, [:role_assignment])
30 end 32 end
31 33
32 end 34 end
app/views/catalog/index.html.erb
@@ -14,8 +14,8 @@ @@ -14,8 +14,8 @@
14 14
15 <ul id="product-list"> 15 <ul id="product-list">
16 <% @products.each do |product| %> 16 <% @products.each do |product| %>
17 - <% extra_content = @plugins.dispatch(:catalog_item_extras, product).collect { |content| instance_eval(&content) } %>  
18 - <% extra_content_list = @plugins.dispatch(:catalog_list_item_extras, product).collect { |content| instance_eval(&content) } %> 17 + <% extra_content = @plugins.dispatch(:catalog_item_extras, product).collect { |content| instance_exec(&content) } %>
  18 + <% extra_content_list = @plugins.dispatch(:catalog_list_item_extras, product).collect { |content| instance_exec(&content) } %>
19 19
20 <% status = [] %> 20 <% status = [] %>
21 <% status << 'not-available' if !product.available %> 21 <% status << 'not-available' if !product.available %>
app/views/events/_month.html.erb
@@ -13,8 +13,8 @@ @@ -13,8 +13,8 @@
13 date.day, 13 date.day,
14 :url => {:action => 'events_by_day', :year => date.year, :month => date.month, :day => date.day, :category_id => @category_id}, 14 :url => {:action => 'events_by_day', :year => date.year, :month => date.month, :day => date.day, :category_id => @category_id},
15 :update => 'events-of-the-day', 15 :update => 'events-of-the-day',
16 - :loading => '$("events-of-the-day").addClassName("loading")',  
17 - :complete => '$("events-of-the-day").removeClassName("loading")' 16 + :loading => "$('events-of-the-day').addClassName('loading')",
  17 + :complete => "$('events-of-the-day').removeClassName('loading')"
18 ) : 18 ) :
19 date.day 19 date.day
20 %> 20 %>
app/views/layouts/application-ng.html.erb
@@ -19,6 +19,9 @@ @@ -19,6 +19,9 @@
19 <meta property="og:site_name" content="<%= profile ? profile.name : @environment.name %>"> 19 <meta property="og:site_name" content="<%= profile ? profile.name : @environment.name %>">
20 <meta property="og:description" content="<%= @page ? truncate(strip_tags(@page.body.to_s), :length => 200) : @environment.name %>"> 20 <meta property="og:description" content="<%= @page ? truncate(strip_tags(@page.body.to_s), :length => 200) : @environment.name %>">
21 21
  22 + <!-- site root -->
  23 + <meta property="noosfero:root" content="<%= Noosfero.root %>"/>
  24 +
22 <% if @page %> 25 <% if @page %>
23 <meta property="article:published_time" content="<%= show_date(@page.published_at) %>"> 26 <meta property="article:published_time" content="<%= show_date(@page.published_at) %>">
24 <% @page.body_images_paths.each do |img| %> 27 <% @page.body_images_paths.each do |img| %>
app/views/manage_products/_edit_description.html.erb
1 <%= render :file => 'shared/tiny_mce', :locals => {:mode => 'simple'} %> 1 <%= render :file => 'shared/tiny_mce', :locals => {:mode => 'simple'} %>
2 <%= remote_form_for(@product, 2 <%= remote_form_for(@product,
3 :loading => "small_loading('product-description-form')", 3 :loading => "small_loading('product-description-form')",
4 - :before => ("tinyMCE.triggerSave()" unless Rails.env == 'test'),  
5 :update => 'product-description', 4 :update => 'product-description',
6 :url => {:controller => 'manage_products', :action => 'edit', :id => @product, :field => 'description'}, 5 :url => {:controller => 'manage_products', :action => 'edit', :id => @product, :field => 'description'},
7 :html => {:id => 'product-description-form', :method => 'post'}) do |f| %> 6 :html => {:id => 'product-description-form', :method => 'post'}) do |f| %>
app/views/manage_products/show.html.erb
@@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
13 <%= render :partial => 'manage_products/display_image' %> 13 <%= render :partial => 'manage_products/display_image' %>
14 </div> 14 </div>
15 <div id='product-extra-content'> 15 <div id='product-extra-content'>
16 - <% extra_content = @plugins.dispatch(:product_info_extras, @product).collect { |content| instance_eval(&content) } %> 16 + <% extra_content = @plugins.dispatch(:product_info_extras, @product).collect { |content| instance_exec(&content) } %>
17 <%= extra_content.join("\n") %> 17 <%= extra_content.join("\n") %>
18 </div> 18 </div>
19 <div id='product-info'> 19 <div id='product-info'>
app/views/profile/_common.html.erb
1 <% unless @action %> 1 <% unless @action %>
2 <% cache_timeout(profile.cache_key + '-profile-general-info', 4.hours) do %> 2 <% cache_timeout(profile.cache_key + '-profile-general-info', 4.hours) do %>
3 - <tr>  
4 - <th colspan='2'>  
5 - <%= _('Content') %>  
6 - </th>  
7 - </tr>  
8 -  
9 - <% profile.blogs.each do |blog| %>  
10 - <tr>  
11 - <td><%= blog.name + ':' %></td>  
12 - <td>  
13 - <%= link_to(n_('One post', '%{num} posts', blog.posts.published.count) % { :num => blog.posts.published.count }, blog.url) %>  
14 - </td>  
15 - </tr>  
16 - <% end %>  
17 - <% profile.image_galleries.each do |gallery| %>  
18 - <tr>  
19 - <td><%= gallery.name + ':' %></td>  
20 - <td>  
21 - <%= link_to(n_('One picture', '%{num} pictures', gallery.images.published.count) % { :num => gallery.images.published.count }, gallery.url) %>  
22 - </td>  
23 - </tr>  
24 - <% end %>  
25 -  
26 - <tr>  
27 - <td><%= _('Events:') %></td>  
28 - <td>  
29 - <%= link_to profile.events.published.count, :controller => 'events', :action => 'events' %>  
30 - </td>  
31 - </tr>  
32 - <tr>  
33 - <td>  
34 - <%= _('Tags:') %>  
35 - </td>  
36 - <td>  
37 - <%= tag_cloud @tags, :id, { :action => 'tags' }, :max_size => 18, :min_size => 10%>  
38 - </td>  
39 - </tr> 3 + <%= display_content %>
40 4
41 <% if !environment.enabled?('disable_categories') && !profile.interests.empty? %> 5 <% if !environment.enabled?('disable_categories') && !profile.interests.empty? %>
42 - <tr>  
43 - <th colspan='2'><%= _('Interests') %></th>  
44 - </tr>  
45 - <% profile.interests.each do |item| %>  
46 - <tr>  
47 - <td></td>  
48 - <td><%= link_to item.name, :controller => 'search', :action => 'category_index', :category_path => item.explode_path %></td>  
49 - </tr>  
50 - <% end %> 6 + <%= display_interests %>
51 <% end %> 7 <% end %>
  8 +
  9 + <%= display_general %>
52 <% end %> 10 <% end %>
53 <% end %> 11 <% end %>
app/views/profile/_organization_profile.html.erb
1 <table> 1 <table>
2 - <tr>  
3 - <th colspan='2'><%= _('Basic information')%></th>  
4 - </tr>  
5 -  
6 - <tr>  
7 - <td class='field-name'><%= _('Members') %></td>  
8 - <td>  
9 - <%= link_to profile.members_count, :controller => 'profile', :action => 'members' %>  
10 - </td>  
11 - </tr>  
12 -  
13 - <%= display_field(_('Type:'), profile, :privacy_setting, true) %>  
14 -  
15 - <%= display_field(_('Location:'), profile, :location, true) %>  
16 -  
17 - <tr>  
18 - <td class='field-name'><%= _('Profile created at:') %></td>  
19 - <td><%= show_date(profile.created_at) %></td>  
20 - </tr>  
21 -  
22 - <% if profile.kind_of?(Enterprise) && profile.environment.enabled?('products_for_enterprises') %>  
23 - <tr>  
24 - <td></td>  
25 - <td>  
26 - <%= link_to _('Products/Services'), :controller => 'catalog', :action => 'index' %>  
27 - </td>  
28 - </tr>  
29 - <% end %>  
30 -  
31 - <tr>  
32 - <td class='field-name'><%= _('Administrators:') %></td>  
33 - <td>  
34 - <%= profile.admins.map { |admin| link_to(admin.short_name, admin.url)}.join(', ') %>  
35 - </td>  
36 - </tr>  
37 - 2 + <%= display_basic_information %>
  3 + <%= display_contact %>
  4 + <%= display_economic %>
38 <%= render :partial => 'common' %> 5 <%= render :partial => 'common' %>
39 </table> 6 </table>
app/views/profile/_person_profile.html.erb
1 <table> 1 <table>
2 - <tr>  
3 - <th colspan='2'><%= _('Basic information')%></th>  
4 - </tr>  
5 - <%= display_field(_('Sex:'), profile, :sex) { |gender| { 'male' => _('Male'), 'female' => _('Female') }[gender] } %>  
6 - <%= display_field(_('Date of birth:'), profile, :birth_date) { |date| show_date(date) }%>  
7 - <%= display_field _('Location:'), profile, :location %>  
8 -  
9 - <%= display_field(_('Type:'), profile, :privacy_setting, true) %>  
10 -  
11 - <tr>  
12 - <td class='field-name'><%= _('Profile created at:') %></td>  
13 - <td><%= show_date(profile.created_at) %></td>  
14 - </tr>  
15 -  
16 - <%= display_contact profile %> 2 + <%= display_basic_information %>
  3 + <%= display_contact %>
  4 + <%= display_location %>
17 5
18 <% cache_timeout(profile.relationships_cache_key, 4.hours) do %> 6 <% cache_timeout(profile.relationships_cache_key, 4.hours) do %>
19 - <%= display_work_info profile %>  
20 -  
21 - <tr>  
22 - <th colspan='2'><%= _('Network')%></th>  
23 - </tr>  
24 - <tr>  
25 - <td><%= _('Friends') + ':' %></td>  
26 - <td><%= link_to profile.friends.count, { :controller => 'profile', :action => 'friends' } %></td>  
27 - </tr>  
28 - <tr>  
29 - <td><%= _('Communities') + ':' %></td>  
30 - <td><%= link_to profile.communities.count, :controller => "profile", :action => 'communities' %></td>  
31 - </tr>  
32 - <% if environment.disabled?('disable_asset_enterprises') %>  
33 - <tr id="person-profile-network-enterprises">  
34 - <td><%= _('Enterprises') + ':' %></td>  
35 - <td><%= link_to profile.enterprises.count, :controller => "profile", :action => 'enterprises' %></td>  
36 - </tr>  
37 - <% end %> 7 + <%= display_work %>
  8 + <%= display_study %>
  9 + <%= display_network %>
38 10
39 <%= render :partial => 'common' %> 11 <%= render :partial => 'common' %>
40 -  
41 <% end %> 12 <% end %>
42 </table> 13 </table>
43 14
app/views/profile/_profile_comment_form.html.erb
@@ -10,8 +10,8 @@ @@ -10,8 +10,8 @@
10 :rows => 1, 10 :rows => 1,
11 :class => 'submit-with-keypress', 11 :class => 'submit-with-keypress',
12 :title => _('Leave your comment'), 12 :title => _('Leave your comment'),
13 - :onfocus => ('if(this.value==this.title){this.value="";this.style.color="#000"};this.style.backgroundImage="url(' + profile_icon(current_person, :icon, false) + ')"' if logged_in?),  
14 - :onblur => ('if(this.value==""){this.value=this.title;this.style.color="#ccc"};this.style.backgroundImage="none"' if logged_in?), 13 + :onfocus => ("if(this.value==this.title){this.value='';this.style.color='#000'};this.style.backgroundImage='url(" + profile_icon(current_person, :icon, false) + ")'" if logged_in?),
  14 + :onblur => ("if(this.value==''){this.value=this.title;this.style.color='#ccc'};this.style.backgroundImage='none'" if logged_in?),
15 :value => _('Leave your comment'), 15 :value => _('Leave your comment'),
16 :style => 'color: #ccc' %> 16 :style => 'color: #ccc' %>
17 <%= hidden_field_tag :source_id, activity.id, :id => "activity_id_#{activity.id}" %> 17 <%= hidden_field_tag :source_id, activity.id, :id => "activity_id_#{activity.id}" %>
app/views/profile/_profile_scrap_reply_form.html.erb
@@ -9,8 +9,8 @@ @@ -9,8 +9,8 @@
9 :rows => 1, 9 :rows => 1,
10 :class => 'submit-with-keypress', 10 :class => 'submit-with-keypress',
11 :title => _('Leave your comment'), 11 :title => _('Leave your comment'),
12 - :onfocus => ('if(this.value==this.title){this.value="";this.style.color="#000"};this.style.backgroundImage="url(' + profile_icon(current_person, :icon, false) + ')"' if logged_in?),  
13 - :onblur => ('if(this.value==""){this.value=this.title;this.style.color="#ccc"};this.style.backgroundImage="none"' if logged_in?), 12 + :onfocus => ("if(this.value==this.title){this.value='';this.style.color='#000'};this.style.backgroundImage='url(" + profile_icon(current_person, :icon, false) + ")'" if logged_in?),
  13 + :onblur => ("if(this.value==''){this.value=this.title;this.style.color='#ccc'};this.style.backgroundImage='none'" if logged_in?),
14 :value => _('Leave your comment') %> 14 :value => _('Leave your comment') %>
15 <%= hidden_field_tag 'scrap[scrap_id]', scrap.id %> 15 <%= hidden_field_tag 'scrap[scrap_id]', scrap.id %>
16 <%= hidden_field_tag 'receiver_id', scrap.sender.id %> 16 <%= hidden_field_tag 'receiver_id', scrap.sender.id %>
app/views/profile_editor/_person_form.html.erb
@@ -25,6 +25,7 @@ @@ -25,6 +25,7 @@
25 <%= optional_field(@person, 'address', labelled_form_field(_('Address (street and number)'), text_field(:profile_data, :address, :rel => _('Address')))) %> 25 <%= optional_field(@person, 'address', labelled_form_field(_('Address (street and number)'), text_field(:profile_data, :address, :rel => _('Address')))) %>
26 <%= optional_field(@person, 'address_reference', labelled_form_field(_('Address reference'), text_field(:profile_data, :address_reference, :rel => _('Address reference')))) %> 26 <%= optional_field(@person, 'address_reference', labelled_form_field(_('Address reference'), text_field(:profile_data, :address_reference, :rel => _('Address reference')))) %>
27 <%= optional_field(@person, 'district', labelled_form_field(_('District'), text_field(:profile_data, :district, :rel => _('District')))) %> 27 <%= optional_field(@person, 'district', labelled_form_field(_('District'), text_field(:profile_data, :district, :rel => _('District')))) %>
  28 +<%= optional_field(@person, 'image', labelled_form_field(_('Image'), file_field(:file, :image, :rel => _('Image')))) %>
28 29
29 <% optional_field(@person, 'schooling') do %> 30 <% optional_field(@person, 'schooling') do %>
30 <div class="formfieldline"> 31 <div class="formfieldline">
app/views/shared/reported_versions/_article.html.erb
@@ -1,10 +0,0 @@ @@ -1,10 +0,0 @@
1 -<ul>  
2 - <li><%= (content_tag('strong', _('Title') + ': ') + article.title) if article.title %> </li>  
3 - <li><%= (content_tag('strong', _('Type') + ': ') + article.class.short_description) %> </li>  
4 - <li>  
5 - <%= (content_tag('strong', _('Original content') + ': ') + link_to(article.name, article.url)) %> <br />  
6 - <%= content_tag('small', _('This link might be unavailable if the content is removed')) %>  
7 - </li>  
8 -</ul>  
9 -  
10 -<%= article_to_html(article) %>  
app/views/shared/reported_versions/_comment.html.erb
@@ -1,10 +0,0 @@ @@ -1,10 +0,0 @@
1 -<ul>  
2 - <li><%= (content_tag('strong', _('Title') + ': ') + comment.title) if comment.title %> </li>  
3 - <li><%= content_tag('strong', _('Type') + ': ') + _('Comment') %> </li>  
4 - <li>  
5 - <%= (content_tag('strong', _('Original content') + ': ') + link_to(comment.title || url_for(comment.url), comment.url)) %> <br />  
6 - <%= content_tag('small', _('This link might be unavailable if the content is removed')) %>  
7 - </li>  
8 -</ul>  
9 -  
10 -<p><%= article_to_html(comment) %></p>  
app/views/shared/reported_versions/_folder.html.erb
@@ -1 +0,0 @@ @@ -1 +0,0 @@
1 -<%= _('Reported folder') + ': ' + link_to(article.name, article.url) %>  
app/views/shared/reported_versions/profile/_article.html.erb 0 → 100644
@@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
  1 +<ul>
  2 + <li><%= (content_tag('strong', _('Title') + ': ') + article.title) if article.title %> </li>
  3 + <li><%= (content_tag('strong', _('Type') + ': ') + article.class.short_description) %> </li>
  4 + <li>
  5 + <%= (content_tag('strong', _('Original content') + ': ') + link_to(article.name, article.url)) %> <br />
  6 + <%= content_tag('small', _('This link might be unavailable if the content is removed')) %>
  7 + </li>
  8 +</ul>
  9 +
  10 +<%= article_to_html(article) %>
app/views/shared/reported_versions/profile/_comment.html.erb 0 → 100644
@@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
  1 +<ul>
  2 + <li><%= (content_tag('strong', _('Title') + ': ') + comment.title) if comment.title %> </li>
  3 + <li><%= content_tag('strong', _('Type') + ': ') + _('Comment') %> </li>
  4 + <li>
  5 + <%= (content_tag('strong', _('Original content') + ': ') + link_to(comment.title || url_for(comment.url), comment.url)) %> <br />
  6 + <%= content_tag('small', _('This link might be unavailable if the content is removed')) %>
  7 + </li>
  8 +</ul>
  9 +
  10 +<p><%= article_to_html(comment) %></p>
app/views/shared/reported_versions/profile/_folder.html.erb 0 → 100644
@@ -0,0 +1 @@ @@ -0,0 +1 @@
  1 +<%= _('Reported folder') + ': ' + link_to(article.name, article.url) %>
app/views/shared/tiny_mce.html.erb
1 -<% extend MacrosHelper %>  
2 -<%= javascript_include_tag 'tinymce/jscripts/tiny_mce/tiny_mce.js' %>  
3 -<%= include_macro_js_files %>  
4 -<script type="text/javascript">  
5 - var myplugins = "searchreplace,print,table,contextmenu,-macrosPlugin";  
6 - var first_line, second_line;  
7 - var mode = '<%= mode ||= false %>'  
8 - <% if mode %>  
9 - first_line = "fontsizeselect,bold,italic,underline,bullist,numlist,justifyleft,justifycenter,justifyright,link,unlink"  
10 - second_line = ""  
11 - <% else %>  
12 - first_line = "print,separator,copy,paste,separator,undo,redo,separator,search,replace,separator,forecolor,fontsizeselect,formatselect"  
13 - second_line = "bold,italic,underline,strikethrough,separator,bullist,numlist,separator,justifyleft,justifycenter,justifyright,justifyfull,separator,link,unlink,image,table,separator,cleanup,code,macros"  
14 - <% macros_with_buttons.each do |macro| %>  
15 - second_line += ',<%=macro.identifier %>'  
16 - <% end %>  
17 - <% end %>  
18 -  
19 - if (tinymce.isIE) {  
20 - // the paste plugin is only useful in Internet Explorer  
21 - myplugins = "paste," + myplugins;  
22 - } 1 +<%
  2 +extend TinymceHelper
  3 +mode ||= false
  4 +%>
23 5
  6 +<%= tinymce_js %>
  7 +<script type="text/javascript">
24 tinymce.create('tinymce.plugins.MacrosPlugin', { 8 tinymce.create('tinymce.plugins.MacrosPlugin', {
25 createControl: function(n, cm) { 9 createControl: function(n, cm) {
26 switch (n) { 10 switch (n) {
@@ -49,56 +33,21 @@ tinymce.create(&#39;tinymce.plugins.MacrosPlugin&#39;, { @@ -49,56 +33,21 @@ tinymce.create(&#39;tinymce.plugins.MacrosPlugin&#39;, {
49 } 33 }
50 }); 34 });
51 35
  36 +function tinymce_macros_setup(editor) {
  37 + <% macros_with_buttons.each do |macro| %>
  38 + editor.addButton('<%= macro.identifier %>', {
  39 + title: <%= macro_title(macro).to_json %>,
  40 + onclick: <%= generate_macro_config_dialog(macro) %>,
  41 + image : '<%= macro.configuration[:icon_path]%>'
  42 + });
  43 + <% end %>
  44 +}
  45 +
52 // Register plugin with a short name 46 // Register plugin with a short name
53 tinymce.PluginManager.add('macrosPlugin', tinymce.plugins.MacrosPlugin); 47 tinymce.PluginManager.add('macrosPlugin', tinymce.plugins.MacrosPlugin);
54 48
55 -tinyMCE.init({  
56 - mode : "textareas",  
57 - editor_selector : "mceEditor",  
58 - theme : "advanced",  
59 - relative_urls : false,  
60 - remove_script_host : false,  
61 - document_base_url : <%= environment.top_url.to_json %>,  
62 - plugins: myplugins,  
63 - theme_advanced_toolbar_location : "top",  
64 - theme_advanced_layout_manager: 'SimpleLayout',  
65 - theme_advanced_buttons1 : first_line,  
66 - theme_advanced_buttons2 : second_line,  
67 - theme_advanced_buttons3 : "",  
68 - theme_advanced_blockformats :"p,address,pre,h2,h3,h4,h5,h6",  
69 - paste_auto_cleanup_on_paste : true,  
70 - paste_insert_word_content_callback : "convertWord",  
71 - paste_use_dialog: false,  
72 - apply_source_formatting : true,  
73 - extended_valid_elements : "applet[style|archive|codebase|code|height|width],comment,iframe[src|style|allowtransparency|frameborder|width|height|scrolling],embed[title|src|type|height|width],audio[controls|autoplay],video[controls|autoplay],source[src|type]",  
74 - content_css: '/stylesheets/tinymce.css,<%= macro_css_files %>',  
75 - language: <%= tinymce_language.inspect %>,  
76 - entity_encoding: 'raw',  
77 - setup : function(ed) {  
78 - <% macros_with_buttons.each do |macro| %>  
79 - ed.addButton('<%= macro.identifier %>', {  
80 - title: <%= macro_title(macro).to_json %>,  
81 - onclick: <%= generate_macro_config_dialog(macro) %>,  
82 - image : '<%= macro.configuration[:icon_path]%>'  
83 - });  
84 - <% end %>  
85 - } 49 +jQuery(document).ready(function () {
  50 + <%= tinymce_init_js :mode => mode %>
86 }); 51 });
87 -  
88 -function convertWord(type, content) {  
89 - switch (type) {  
90 - // Gets executed before the built in logic performes it's cleanups  
91 - case "before":  
92 - //content = content.toLowerCase(); // Some dummy logic  
93 - break;  
94 -  
95 - // Gets executed after the built in logic performes it's cleanups  
96 - case "after":  
97 - content = content.replace(/<!--\s*-->/, '');  
98 - break;  
99 - }  
100 -  
101 - return content;  
102 -}  
103 -  
104 </script> 52 </script>
  53 +
app/views/task_mailer/generic_message.text.erb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +<%= _('Dear %s,') % @requestor %>
  2 +
  3 +<%= word_wrap(@message) %>
  4 +
  5 +<%= _('Greetings,') %>
  6 +
  7 +--
  8 +<%= _('%s team.') % @environment %>
  9 +<%= @url %>
app/views/task_mailer/task_activated.text.erb
@@ -1 +0,0 @@ @@ -1 +0,0 @@
1 -task_cancelled.text.erb  
2 \ No newline at end of file 0 \ No newline at end of file
app/views/task_mailer/task_cancelled.text.erb
@@ -1,9 +0,0 @@ @@ -1,9 +0,0 @@
1 -<%= _('Dear %s,') % @requestor %>  
2 -  
3 -<%= word_wrap(@message) %>  
4 -  
5 -<%= _('Greetings,') %>  
6 -  
7 ---  
8 -<%= _('%s team.') % @environment %>  
9 -<%= @url %>  
app/views/task_mailer/task_created.text.erb
@@ -1 +0,0 @@ @@ -1 +0,0 @@
1 -task_cancelled.text.erb  
2 \ No newline at end of file 0 \ No newline at end of file
app/views/task_mailer/task_finished.text.erb
@@ -1 +0,0 @@ @@ -1 +0,0 @@
1 -task_cancelled.text.erb  
2 \ No newline at end of file 0 \ No newline at end of file
config/application.rb
@@ -108,13 +108,19 @@ module Noosfero @@ -108,13 +108,19 @@ module Noosfero
108 108
109 # Your secret key for verifying cookie session data integrity. 109 # Your secret key for verifying cookie session data integrity.
110 # If you change this key, all old sessions will become invalid! 110 # If you change this key, all old sessions will become invalid!
111 - # Make sure the secret is at least 30 characters and all random, 111 + # Make sure the secret is at least 30 characters and all random,
112 # no regular words or you'll be exposed to dictionary attacks. 112 # no regular words or you'll be exposed to dictionary attacks.
113 config.secret_token = noosfero_session_secret 113 config.secret_token = noosfero_session_secret
114 config.action_dispatch.session = { 114 config.action_dispatch.session = {
115 :key => '_noosfero_session', 115 :key => '_noosfero_session',
116 } 116 }
117 117
  118 + config.time_zone = File.read('/etc/timezone').split("\n").first
  119 + config.active_record.default_timezone = :local
  120 +
  121 + config.paths['db/migrate'] += Dir.glob "#{Rails.root}/{baseplugins,config/plugins}/*/db/migrate"
  122 + config.i18n.load_path += Dir.glob "#{Rails.root}/{baseplugins,config/plugins}/*/locales/*.{rb,yml}"
  123 +
118 Noosfero::Plugin.setup(config) 124 Noosfero::Plugin.setup(config)
119 125
120 end 126 end
config/cucumber.yml
1 <% base_requires = '-r features/support -r features/step_definitions' %> 1 <% base_requires = '-r features/support -r features/step_definitions' %>
2 -<% default_options = "--color --format progress --strict --tags ~@selenium --tags ~@selenium-fixme --tags ~@fixme --exclude features/support/selenium.rb #{base_requires}" %> 2 +<% default_options = "--format progress --strict --tags ~@selenium --tags ~@selenium-fixme --tags ~@fixme --exclude features/support/selenium.rb #{base_requires}" %>
  3 +<%
  4 + default_options += ' --color' if $stdout.isatty
  5 +%>
3 <% selenium_options = "--strict --tags @selenium #{base_requires}" %> 6 <% selenium_options = "--strict --tags @selenium #{base_requires}" %>
4 7
5 default: <%= default_options %> 8 default: <%= default_options %>
config/initializers/activities_counter_cache.rb
1 -if Delayed::Backend::ActiveRecord::Job.table_exists? 1 +if Delayed::Backend::ActiveRecord::Job.table_exists? &&
  2 + Delayed::Backend::ActiveRecord::Job.attribute_names.include?('queue')
2 job = Delayed::Backend::ActiveRecord::Job.all :conditions => ['handler LIKE ?', "%ActivitiesCounterCacheJob%"] 3 job = Delayed::Backend::ActiveRecord::Job.all :conditions => ['handler LIKE ?', "%ActivitiesCounterCacheJob%"]
3 if job.blank? 4 if job.blank?
4 Delayed::Backend::ActiveRecord::Job.enqueue(ActivitiesCounterCacheJob.new, {:priority => -3}) 5 Delayed::Backend::ActiveRecord::Job.enqueue(ActivitiesCounterCacheJob.new, {:priority => -3})
config/initializers/i18n.rb
1 # necessary for I18n.default_locale to work 1 # necessary for I18n.default_locale to work
2 require 'i18n/backend/fallbacks' 2 require 'i18n/backend/fallbacks'
3 I18n.backend.class.send :include, I18n::Backend::Fallbacks 3 I18n.backend.class.send :include, I18n::Backend::Fallbacks
4 - 4 +I18n.enforce_available_locales = false
config/initializers/log_memory_consumption.rb
@@ -1,5 +0,0 @@ @@ -1,5 +0,0 @@
1 -if Delayed::Backend::ActiveRecord::Job.table_exists?  
2 - jobs = Delayed::Backend::ActiveRecord::Job.all :conditions => ['handler LIKE ?', "%LogMemoryConsumptionJob%"]  
3 - jobs.map(&:destroy) if jobs.present?  
4 - Delayed::Backend::ActiveRecord::Job.enqueue(LogMemoryConsumptionJob.new)  
5 -end  
config/initializers/newrelic.rb 0 → 100644
@@ -0,0 +1,2 @@ @@ -0,0 +1,2 @@
  1 +# Load newrelic agent if its config file is defined.
  2 +require 'newrelic_rpm' if File.exist?(File.dirname(__FILE__) + '/../newrelic.yml')
config/initializers/person_notification.rb
1 -if Delayed::Backend::ActiveRecord::Job.table_exists? 1 +if Delayed::Backend::ActiveRecord::Job.table_exists? &&
  2 + Delayed::Backend::ActiveRecord::Job.attribute_names.include?('queue')
2 PersonNotifier.schedule_all_next_notification_mail 3 PersonNotifier.schedule_all_next_notification_mail
3 end 4 end
db/migrate/20140708115518_index_domains_filtered_fields.rb 0 → 100644
@@ -0,0 +1,10 @@ @@ -0,0 +1,10 @@
  1 +class IndexDomainsFilteredFields < ActiveRecord::Migration
  2 +
  3 + def self.up
  4 + add_index :domains, [:name]
  5 + add_index :domains, [:is_default]
  6 + add_index :domains, [:owner_id, :owner_type]
  7 + add_index :domains, [:owner_id, :owner_type, :is_default]
  8 + end
  9 +
  10 +end
db/migrate/20140708121356_index_articles_filtered_fields.rb 0 → 100644
@@ -0,0 +1,12 @@ @@ -0,0 +1,12 @@
  1 +class IndexArticlesFilteredFields < ActiveRecord::Migration
  2 + def self.up
  3 + %w[articles article_versions].each do |table|
  4 + add_index table.to_sym, [:path]
  5 + add_index table.to_sym, [:path, :profile_id]
  6 + end
  7 + add_index :articles, [:type]
  8 + add_index :articles, [:type, :parent_id]
  9 + add_index :articles, [:type, :profile_id]
  10 + end
  11 +
  12 +end
db/migrate/20140709212646_add_spam_comments_counter_cache_to_articles.rb
@@ -2,7 +2,10 @@ class AddSpamCommentsCounterCacheToArticles &lt; ActiveRecord::Migration @@ -2,7 +2,10 @@ class AddSpamCommentsCounterCacheToArticles &lt; ActiveRecord::Migration
2 def self.up 2 def self.up
3 add_column :articles, :spam_comments_count, :integer, :default => 0 3 add_column :articles, :spam_comments_count, :integer, :default => 0
4 add_column :article_versions, :spam_comments_count, :integer, :default => 0 4 add_column :article_versions, :spam_comments_count, :integer, :default => 0
5 - execute "update articles set spam_comments_count = (select count(*) from comments where comments.source_id = articles.id and comments.source_type = 'Article' and comments.spam = 't');" 5 +
  6 + execute("SELECT comments.source_id as source_id, count(comments.id) as comments_count FROM comments LEFT OUTER JOIN articles ON articles.id = source_id WHERE comments.source_type = 'Article' AND comments.spam = 't' GROUP BY comments.source_id;").each do |data|
  7 + execute("UPDATE articles SET spam_comments_count = '#{data['comments_count']}' WHERE id = #{data['source_id']}")
  8 + end
6 end 9 end
7 10
8 def self.down 11 def self.down
db/migrate/20140709224246_create_real_relation_between_article_and_author.rb
@@ -4,8 +4,10 @@ class CreateRealRelationBetweenArticleAndAuthor &lt; ActiveRecord::Migration @@ -4,8 +4,10 @@ class CreateRealRelationBetweenArticleAndAuthor &lt; ActiveRecord::Migration
4 add_column :article_versions, :author_id, :integer 4 add_column :article_versions, :author_id, :integer
5 5
6 # Set article's author as the first version's last_changed_by_id. 6 # Set article's author as the first version's last_changed_by_id.
7 - execute "update articles set author_id = (select article_versions.last_changed_by_id from article_versions where article_versions.article_id = articles.id and article_versions.version = 1 limit 1)"  
8 - end 7 + execute("UPDATE article_versions SET author_id = last_changed_by_id")
  8 +
  9 + execute("UPDATE articles SET author_id = article_versions.author_id FROM article_versions WHERE article_versions.article_id = articles.id AND article_versions.version = 1")
  10 + end
9 11
10 def self.down 12 def self.down
11 remove_column :articles, :author_id 13 remove_column :articles, :author_id
db/migrate/20140724134601_fix_yaml_encoding.rb
1 class FixYamlEncoding < ActiveRecord::Migration 1 class FixYamlEncoding < ActiveRecord::Migration
2 def self.up 2 def self.up
3 - fix_encoding(Block, 'settings')  
4 - fix_encoding(Product, 'data')  
5 - fix_encoding(Environment, 'settings')  
6 - fix_encoding(Profile, 'data')  
7 - fix_encoding(ActionTracker::Record, 'params')  
8 - fix_encoding(Article, 'setting')  
9 - fix_encoding(Task, 'data') 3 + ActiveRecord::Base.transaction do
  4 + fix_encoding(Environment, 'settings')
  5 + fix_encoding(Profile, 'data')
  6 + fix_encoding(Product, 'data')
  7 + fix_encoding(ActionTracker::Record, 'params')
  8 + fix_encoding(Article, 'setting')
  9 + fix_encoding(Task, 'data')
  10 + fix_encoding(Block, 'settings')
  11 + end
10 end 12 end
11 13
12 def self.down 14 def self.down
@@ -16,15 +18,34 @@ class FixYamlEncoding &lt; ActiveRecord::Migration @@ -16,15 +18,34 @@ class FixYamlEncoding &lt; ActiveRecord::Migration
16 private 18 private
17 19
18 def self.fix_encoding(model, param) 20 def self.fix_encoding(model, param)
19 - result = model.find(:all, :conditions => "#{param} LIKE '%!binary%'") 21 + result = model.all
20 puts "Fixing #{result.count} rows of #{model} (#{param})" 22 puts "Fixing #{result.count} rows of #{model} (#{param})"
21 - result.each {|r| r.update_column(param, deep_fix(r.send(param)).to_yaml)} 23 + result.each do |r|
  24 + begin
  25 + yaml = r.send(param)
  26 + # if deserialization failed then a string is returned
  27 + if yaml.is_a? String
  28 + yaml.gsub! ': `', ': '
  29 + yaml = YAML.load yaml
  30 + end
  31 + r.update_column param, deep_fix(yaml).to_yaml
  32 + rescue => e
  33 + puts "FAILED #{r.inspect}"
  34 + puts e.message
  35 + end
  36 + end
22 end 37 end
23 38
24 def self.deep_fix(hash) 39 def self.deep_fix(hash)
25 hash.each do |value| 40 hash.each do |value|
26 - value.force_encoding('UTF-8') if value.is_a?(String) && !value.frozen? && value.encoding == Encoding::ASCII_8BIT  
27 deep_fix(value) if value.respond_to?(:each) 41 deep_fix(value) if value.respond_to?(:each)
  42 + if value.is_a? String and not value.frozen?
  43 + if value.encoding == Encoding::ASCII_8BIT
  44 + value.force_encoding "utf-8"
  45 + else
  46 + value.encode!("iso-8859-1").force_encoding("utf-8")
  47 + end
  48 + end
28 end 49 end
29 end 50 end
30 51
db/migrate/20140724180943_add_index_to_blog_posts_sort.rb 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +class AddIndexToBlogPostsSort < ActiveRecord::Migration
  2 + def self.up
  3 + %w[articles article_versions].each do |table|
  4 + add_index table.to_sym, [:published_at, :id]
  5 + end
  6 + end
  7 +
  8 + def self.down
  9 + %w[articles article_versions].each do |table|
  10 + remove_index table.to_sym, [:published_at, :id]
  11 + end
  12 + end
  13 +end
@@ -95,12 +95,15 @@ ActiveRecord::Schema.define(:version =&gt; 20140827191326) do @@ -95,12 +95,15 @@ ActiveRecord::Schema.define(:version =&gt; 20140827191326) do
95 t.integer "license_id" 95 t.integer "license_id"
96 t.integer "image_id" 96 t.integer "image_id"
97 t.integer "position" 97 t.integer "position"
98 - t.integer "created_by_id"  
99 t.integer "spam_comments_count", :default => 0 98 t.integer "spam_comments_count", :default => 0
100 t.integer "author_id" 99 t.integer "author_id"
  100 + t.integer "created_by_id"
101 end 101 end
102 102
103 add_index "article_versions", ["article_id"], :name => "index_article_versions_on_article_id" 103 add_index "article_versions", ["article_id"], :name => "index_article_versions_on_article_id"
  104 + add_index "article_versions", ["path", "profile_id"], :name => "index_article_versions_on_path_and_profile_id"
  105 + add_index "article_versions", ["path"], :name => "index_article_versions_on_path"
  106 + add_index "article_versions", ["published_at", "id"], :name => "index_article_versions_on_published_at_and_id"
104 107
105 create_table "articles", :force => true do |t| 108 create_table "articles", :force => true do |t|
106 t.string "name" 109 t.string "name"
@@ -143,9 +146,9 @@ ActiveRecord::Schema.define(:version =&gt; 20140827191326) do @@ -143,9 +146,9 @@ ActiveRecord::Schema.define(:version =&gt; 20140827191326) do
143 t.integer "license_id" 146 t.integer "license_id"
144 t.integer "image_id" 147 t.integer "image_id"
145 t.integer "position" 148 t.integer "position"
146 - t.integer "created_by_id"  
147 t.integer "spam_comments_count", :default => 0 149 t.integer "spam_comments_count", :default => 0
148 t.integer "author_id" 150 t.integer "author_id"
  151 + t.integer "created_by_id"
149 end 152 end
150 153
151 add_index "articles", ["comments_count"], :name => "index_articles_on_comments_count" 154 add_index "articles", ["comments_count"], :name => "index_articles_on_comments_count"
@@ -153,9 +156,15 @@ ActiveRecord::Schema.define(:version =&gt; 20140827191326) do @@ -153,9 +156,15 @@ ActiveRecord::Schema.define(:version =&gt; 20140827191326) do
153 add_index "articles", ["hits"], :name => "index_articles_on_hits" 156 add_index "articles", ["hits"], :name => "index_articles_on_hits"
154 add_index "articles", ["name"], :name => "index_articles_on_name" 157 add_index "articles", ["name"], :name => "index_articles_on_name"
155 add_index "articles", ["parent_id"], :name => "index_articles_on_parent_id" 158 add_index "articles", ["parent_id"], :name => "index_articles_on_parent_id"
  159 + add_index "articles", ["path", "profile_id"], :name => "index_articles_on_path_and_profile_id"
  160 + add_index "articles", ["path"], :name => "index_articles_on_path"
156 add_index "articles", ["profile_id"], :name => "index_articles_on_profile_id" 161 add_index "articles", ["profile_id"], :name => "index_articles_on_profile_id"
  162 + add_index "articles", ["published_at", "id"], :name => "index_articles_on_published_at_and_id"
157 add_index "articles", ["slug"], :name => "index_articles_on_slug" 163 add_index "articles", ["slug"], :name => "index_articles_on_slug"
158 add_index "articles", ["translation_of_id"], :name => "index_articles_on_translation_of_id" 164 add_index "articles", ["translation_of_id"], :name => "index_articles_on_translation_of_id"
  165 + add_index "articles", ["type", "parent_id"], :name => "index_articles_on_type_and_parent_id"
  166 + add_index "articles", ["type", "profile_id"], :name => "index_articles_on_type_and_profile_id"
  167 + add_index "articles", ["type"], :name => "index_articles_on_type"
159 168
160 create_table "articles_categories", :id => false, :force => true do |t| 169 create_table "articles_categories", :id => false, :force => true do |t|
161 t.integer "article_id" 170 t.integer "article_id"
@@ -277,6 +286,11 @@ ActiveRecord::Schema.define(:version =&gt; 20140827191326) do @@ -277,6 +286,11 @@ ActiveRecord::Schema.define(:version =&gt; 20140827191326) do
277 t.string "google_maps_key" 286 t.string "google_maps_key"
278 end 287 end
279 288
  289 + add_index "domains", ["is_default"], :name => "index_domains_on_is_default"
  290 + add_index "domains", ["name"], :name => "index_domains_on_name"
  291 + add_index "domains", ["owner_id", "owner_type", "is_default"], :name => "index_domains_on_owner_id_and_owner_type_and_is_default"
  292 + add_index "domains", ["owner_id", "owner_type"], :name => "index_domains_on_owner_id_and_owner_type"
  293 +
280 create_table "environments", :force => true do |t| 294 create_table "environments", :force => true do |t|
281 t.string "name" 295 t.string "name"
282 t.string "contact_email" 296 t.string "contact_email"
debian/bundle/config
@@ -1,3 +0,0 @@ @@ -1,3 +0,0 @@
1 ----  
2 -BUNDLE_WITHOUT: test:cucumber  
3 -  
debian/changelog
  1 +noosfero (1.0~rc4) wheezy-test; urgency=low
  2 +
  3 + * Fourth release candidate
  4 +
  5 + -- Antonio Terceiro <vagrant@wheezy-base> Wed, 19 Nov 2014 10:31:16 -0300
  6 +
  7 +noosfero (1.0~rc3) wheezy-test; urgency=low
  8 +
  9 + * Third release candidate to Noosfero 1.0
  10 +
  11 + -- Antonio Terceiro <terceiro@debian.org> Fri, 12 Sep 2014 16:20:58 -0300
  12 +
  13 +noosfero (1.0~rc2) wheezy-test; urgency=low
  14 +
  15 + * Second 1.0 release candidate
  16 +
  17 + -- Antonio Terceiro <terceiro@debian.org> Fri, 12 Sep 2014 13:01:11 -0300
  18 +
1 noosfero (1.0~rc1) wheezy-test; urgency=low 19 noosfero (1.0~rc1) wheezy-test; urgency=low
2 20
3 * First 1.0 release candidate 21 * First 1.0 release candidate
@@ -10,6 +28,18 @@ noosfero (0.99.0~rc20140618202455) wheezy-test; urgency=low @@ -10,6 +28,18 @@ noosfero (0.99.0~rc20140618202455) wheezy-test; urgency=low
10 28
11 -- Rodrigo Souto <rodrigo@colivre.coop.br> Wed, 18 Jun 2014 20:25:01 +0000 29 -- Rodrigo Souto <rodrigo@colivre.coop.br> Wed, 18 Jun 2014 20:25:01 +0000
12 30
  31 +noosfero (0.47.5) unstable; urgency=low
  32 +
  33 + * Bugfixes release
  34 +
  35 + -- Daniela Soares Feitosa <daniela@colivre.coop.br> Thu, 23 Oct 2014 02:24:14 +0000
  36 +
  37 +noosfero (0.47.4) unstable; urgency=low
  38 +
  39 + * Bugfixes and performance optimizations
  40 +
  41 + -- Rodrigo Souto <rodrigo@colivre.coop.br> Thu, 21 Aug 2014 19:25:37 +0000
  42 +
13 noosfero (0.47.3) unstable; urgency=low 43 noosfero (0.47.3) unstable; urgency=low
14 44
15 * Bugfixes release 45 * Bugfixes release
debian/control
@@ -9,7 +9,7 @@ Build-Depends: @@ -9,7 +9,7 @@ Build-Depends:
9 ruby-gettext, 9 ruby-gettext,
10 ruby-sqlite3, 10 ruby-sqlite3,
11 rake, 11 rake,
12 - rails3 (>= 3.2.6-1~), 12 + rails3 (>= 3.2.19-1~),
13 ruby-rspec, 13 ruby-rspec,
14 ruby-rspec-rails, 14 ruby-rspec-rails,
15 ruby-will-paginate, 15 ruby-will-paginate,
@@ -30,12 +30,14 @@ Vcs-Browser: http://git.colivre.coop.br/?p=noosfero.git @@ -30,12 +30,14 @@ Vcs-Browser: http://git.colivre.coop.br/?p=noosfero.git
30 30
31 Package: noosfero 31 Package: noosfero
32 Architecture: all 32 Architecture: all
  33 +Pre-Depends: ruby1.8 (>= 1.8.7.358)
33 Depends: 34 Depends:
34 rails3 (>= 3.2.6-1~), 35 rails3 (>= 3.2.6-1~),
35 ruby (>= 1:1.9.3), 36 ruby (>= 1:1.9.3),
36 rake, 37 rake,
37 ruby-dalli, 38 ruby-dalli,
38 ruby-exception-notification, 39 ruby-exception-notification,
  40 + ruby-gettext,
39 ruby-fast-gettext, 41 ruby-fast-gettext,
40 ruby-pg, 42 ruby-pg,
41 ruby-rmagick, 43 ruby-rmagick,
@@ -49,6 +51,7 @@ Depends: @@ -49,6 +51,7 @@ Depends:
49 ruby-hpricot, 51 ruby-hpricot,
50 ruby-nokogiri, 52 ruby-nokogiri,
51 ruby-acts-as-taggable-on, 53 ruby-acts-as-taggable-on,
  54 + ruby-progressbar,
52 ruby-prototype-rails, 55 ruby-prototype-rails,
53 ruby-rails-autolink, 56 ruby-rails-autolink,
54 memcached, 57 memcached,
debian/filter-gemfile 0 → 100755
@@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
  1 +#!/bin/sh
  2 +
  3 +set -e
  4 +
  5 +sed -e '/^group\s*:\(test\|cucumber\)/,/^end/ d' Gemfile
debian/noosfero.install
@@ -7,10 +7,6 @@ util usr/share/noosfero @@ -7,10 +7,6 @@ util usr/share/noosfero
7 Rakefile usr/share/noosfero 7 Rakefile usr/share/noosfero
8 vendor usr/share/noosfero 8 vendor usr/share/noosfero
9 9
10 -Gemfile usr/share/noosfero  
11 -Gemfile.lock usr/share/noosfero  
12 -debian/bundle/config usr/share/noosfero/.bundle  
13 -  
14 config/application.rb usr/share/noosfero/config 10 config/application.rb usr/share/noosfero/config
15 config/boot.rb usr/share/noosfero/config 11 config/boot.rb usr/share/noosfero/config
16 config/environment.rb usr/share/noosfero/config 12 config/environment.rb usr/share/noosfero/config
debian/noosfero.links
@@ -15,3 +15,4 @@ var/lib/noosfero-data/public/thumbnails usr/share/noosfero/public/th @@ -15,3 +15,4 @@ var/lib/noosfero-data/public/thumbnails usr/share/noosfero/public/th
15 usr/share/noosfero/public/designs/themes/noosfero usr/share/noosfero/public/designs/themes/default 15 usr/share/noosfero/public/designs/themes/noosfero usr/share/noosfero/public/designs/themes/default
16 usr/share/noosfero/public/designs/icons/tango usr/share/noosfero/public/designs/icons/default 16 usr/share/noosfero/public/designs/icons/tango usr/share/noosfero/public/designs/icons/default
17 usr/share/noosfero/script/noosfero-plugins usr/sbin/noosfero-plugins 17 usr/share/noosfero/script/noosfero-plugins usr/sbin/noosfero-plugins
  18 +/dev/null usr/share/noosfero/Gemfile.lock
@@ -20,6 +20,10 @@ override_dh_link: @@ -20,6 +20,10 @@ override_dh_link:
20 dh_link usr/lib/noosfero/dbinstall usr/share/dbconfig-common/scripts/noosfero/install/$$db; \ 20 dh_link usr/lib/noosfero/dbinstall usr/share/dbconfig-common/scripts/noosfero/install/$$db; \
21 done 21 done
22 22
  23 +override_dh_auto_install:
  24 + dh_auto_install
  25 + debian/filter-gemfile > $(CURDIR)/debian/noosfero/usr/share/noosfero/Gemfile
  26 +
23 override_dh_installinit: 27 override_dh_installinit:
24 dh_installinit -pnoosfero --onlyscripts 28 dh_installinit -pnoosfero --onlyscripts
25 29
etc/init.d/noosfero
@@ -45,7 +45,7 @@ if [ -z &quot;$NOOSFERO_DIR&quot; ] || [ -z &quot;$NOOSFERO_USER&quot; ]; then @@ -45,7 +45,7 @@ if [ -z &quot;$NOOSFERO_DIR&quot; ] || [ -z &quot;$NOOSFERO_USER&quot; ]; then
45 fi 45 fi
46 46
47 if test -x /usr/sbin/noosfero-check-dbconfig ; then 47 if test -x /usr/sbin/noosfero-check-dbconfig ; then
48 - if ! noosfero-check-dbconfig; then 48 + if ! /usr/sbin/noosfero-check-dbconfig; then
49 echo "Noosfero database access not configured, service disabled." 49 echo "Noosfero database access not configured, service disabled."
50 exit 0 50 exit 0
51 fi 51 fi
etc/noosfero/varnish-accept-language.vcl
@@ -6,7 +6,14 @@ C{ @@ -6,7 +6,14 @@ C{
6 /* 6 /*
7 * Accept-language header normalization 7 * Accept-language header normalization
8 * 8 *
9 - * Cosimo, 21/01/2010 9 + * - Parses client Accept-Language HTTP header
  10 + * - Tries to find the best match with the supported languages
  11 + * - Writes the best match as req.http.X-Varnish-Accept-Language
  12 + *
  13 + * First version: Cosimo, 21/Jan/2010
  14 + * Last update: Cosimo, 03/Nov/2011
  15 + *
  16 + * http://github.com/cosimo/varnish-accept-language
10 * 17 *
11 */ 18 */
12 19
@@ -16,11 +23,12 @@ C{ @@ -16,11 +23,12 @@ C{
16 #include <string.h> 23 #include <string.h>
17 24
18 #define DEFAULT_LANGUAGE "en" 25 #define DEFAULT_LANGUAGE "en"
19 -#define SUPPORTED_LANGUAGES ":de:fr:es:ru:pt:hy:en:" 26 +#define SUPPORTED_LANGUAGES ":de:eo:es:fr:hy:it:pt:ru:"
20 27
21 #define vcl_string char 28 #define vcl_string char
22 -#define LANG_LIST_SIZE 16  
23 -#define LANG_MAXLEN 16 29 +#define LANG_LIST_SIZE 16
  30 +#define HDR_MAXLEN 256
  31 +#define LANG_MAXLEN 8
24 #define RETURN_LANG(x) { \ 32 #define RETURN_LANG(x) { \
25 strncpy(lang, x, LANG_MAXLEN); \ 33 strncpy(lang, x, LANG_MAXLEN); \
26 return; \ 34 return; \
@@ -64,9 +72,8 @@ int is_supported(vcl_string *lang) { @@ -64,9 +72,8 @@ int is_supported(vcl_string *lang) {
64 strncat(match_str, lang, LANG_MAXLEN); 72 strncat(match_str, lang, LANG_MAXLEN);
65 strncat(match_str, ":\0", 2); 73 strncat(match_str, ":\0", 2);
66 74
67 - if (strstr(supported_languages, match_str)) { 75 + if (strstr(supported_languages, match_str))
68 is_supported = 1; 76 is_supported = 1;
69 - }  
70 77
71 return is_supported; 78 return is_supported;
72 } 79 }
@@ -90,6 +97,7 @@ void select_language(const vcl_string *incoming_header, char *lang) { @@ -90,6 +97,7 @@ void select_language(const vcl_string *incoming_header, char *lang) {
90 vcl_string *lang_tok = NULL; 97 vcl_string *lang_tok = NULL;
91 vcl_string root_lang[3]; 98 vcl_string root_lang[3];
92 vcl_string *header; 99 vcl_string *header;
  100 + vcl_string header_copy[HDR_MAXLEN];
93 vcl_string *pos = NULL; 101 vcl_string *pos = NULL;
94 vcl_string *q_spec = NULL; 102 vcl_string *q_spec = NULL;
95 unsigned int curr_lang = 0, i = 0; 103 unsigned int curr_lang = 0, i = 0;
@@ -106,7 +114,7 @@ void select_language(const vcl_string *incoming_header, char *lang) { @@ -106,7 +114,7 @@ void select_language(const vcl_string *incoming_header, char *lang) {
106 RETURN_DEFAULT_LANG; 114 RETURN_DEFAULT_LANG;
107 115
108 /* Tokenize Accept-Language */ 116 /* Tokenize Accept-Language */
109 - header = (vcl_string *) incoming_header; 117 + header = strncpy(header_copy, incoming_header, sizeof(header_copy));
110 118
111 while ((lang_tok = strtok_r(header, " ,", &pos))) { 119 while ((lang_tok = strtok_r(header, " ,", &pos))) {
112 120
@@ -137,7 +145,8 @@ void select_language(const vcl_string *incoming_header, char *lang) { @@ -137,7 +145,8 @@ void select_language(const vcl_string *incoming_header, char *lang) {
137 header = NULL; 145 header = NULL;
138 146
139 /* Break out if stored max no. of languages */ 147 /* Break out if stored max no. of languages */
140 - if (curr_lang >= LANG_MAXLEN) break; 148 + if (curr_lang >= LANG_LIST_SIZE)
  149 + break;
141 } 150 }
142 151
143 /* Sort by priority */ 152 /* Sort by priority */
@@ -157,12 +166,11 @@ void vcl_rewrite_accept_language(const struct sess *sp) { @@ -157,12 +166,11 @@ void vcl_rewrite_accept_language(const struct sess *sp) {
157 vcl_string *in_hdr; 166 vcl_string *in_hdr;
158 vcl_string lang[LANG_MAXLEN]; 167 vcl_string lang[LANG_MAXLEN];
159 168
160 - memset(lang, 0, LANG_MAXLEN);  
161 -  
162 /* Get Accept-Language header from client */ 169 /* Get Accept-Language header from client */
163 in_hdr = VRT_GetHdr(sp, HDR_REQ, "\020Accept-Language:"); 170 in_hdr = VRT_GetHdr(sp, HDR_REQ, "\020Accept-Language:");
164 171
165 /* Normalize and filter out by list of supported languages */ 172 /* Normalize and filter out by list of supported languages */
  173 + memset(lang, 0, sizeof(lang));
166 select_language(in_hdr, lang); 174 select_language(in_hdr, lang);
167 175
168 /* By default, use a different header name: don't mess with backend logic */ 176 /* By default, use a different header name: don't mess with backend logic */
@@ -191,3 +199,4 @@ sub vcl_fetch { @@ -191,3 +199,4 @@ sub vcl_fetch {
191 set beresp.http.Vary = "X-Varnish-Accept-Language"; 199 set beresp.http.Vary = "X-Varnish-Accept-Language";
192 } 200 }
193 } 201 }
  202 +
features/change_organization_name.feature
@@ -1,36 +0,0 @@ @@ -1,36 +0,0 @@
1 -Feature: change organization name  
2 - As an organization's admin  
3 - I want to change it's name  
4 - In order to keep it's name consistent  
5 -  
6 - Scenario: changing community's name  
7 - Given the following communities  
8 - | identifier | name |  
9 - | sample-community | Sample Community |  
10 - And the following users  
11 - | login | name |  
12 - | joaosilva | Joao Silva |  
13 - And "Joao Silva" is admin of "Sample Community"  
14 - And I am logged in as "joaosilva"  
15 - And I am on sample-community's control panel  
16 - And I follow "Community Info and settings"  
17 - And I fill in "Name" with "New Sample Community"  
18 - When I press "Save"  
19 - Then I should be on sample-community's control panel  
20 - And I should see "New Sample Community" within "title"  
21 -  
22 - Scenario: changing enterprise's name  
23 - Given the following enterprises  
24 - | identifier | name |  
25 - | sample-enterprise | Sample Enterprise |  
26 - And the following users  
27 - | login | name |  
28 - | joaosilva | Joao Silva |  
29 - And "Joao Silva" is admin of "Sample Enterprise"  
30 - And I am logged in as "joaosilva"  
31 - And I am on sample-enterprise's control panel  
32 - And I follow "Enterprise Info and settings"  
33 - And I fill in "Name" with "New Sample Enterprise"  
34 - When I press "Save"  
35 - Then I should be on sample-enterprise's control panel  
36 - And I should see "New Sample Enterprise" within "title"  
features/chat.feature
@@ -1,145 +0,0 @@ @@ -1,145 +0,0 @@
1 -Feature: chat  
2 - As a Noosfero user  
3 - I want to chat with my friends  
4 -  
5 - Background:  
6 - Given the following users  
7 - | login | name |  
8 - | tame | Tame |  
9 - | mariasilva | Maria Silva |  
10 - | josesilva | Jose Silva |  
11 - And "tame" is online in chat  
12 - And "mariasilva" is online in chat  
13 - And "josesilva" is online in chat  
14 - And "tame" is friend of "mariasilva"  
15 - And "tame" is friend of "josesilva"  
16 -  
17 - @selenium  
18 - Scenario: provide link to open chat  
19 - Given feature "xmpp_chat" is enabled on environment  
20 - And I am logged in as "tame"  
21 - Then I should see "Open chat" within "#user"  
22 -  
23 - @selenium  
24 - Scenario: provide the chat online users content  
25 - Given feature "xmpp_chat" is enabled on environment  
26 - And I am logged in as "tame"  
27 - Then I should see "Friends in chat "  
28 -  
29 - @selenium  
30 - Scenario: provide the chat online users list  
31 - Given the profile "tame" has no blocks  
32 - And feature "xmpp_chat" is enabled on environment  
33 - And I am logged in as "tame"  
34 - And I go to tame's profile  
35 - When I follow "chat-online-users-title"  
36 - Then I should see "Maria Silva"  
37 - And I should see "Jose Silva"  
38 -  
39 - Scenario: not provide link to chat when environment not support that  
40 - Given I am logged in as "tame"  
41 - Then I should not see "Open chat" within "#user"  
42 -  
43 - Scenario: not provide link to chat when the user is logged out  
44 - Given I am on tame's homepage  
45 - Then I should not see "Open chat" within "#user"  
46 -  
47 - @selenium  
48 - Scenario: not provide the chat online users list when environment not support that  
49 - Given I am logged in as "tame"  
50 - Then I should not see "Friends in chat "  
51 -  
52 - Scenario: block access to chat when environment not support that  
53 - Given I am logged in as "tame"  
54 - When I go to chat  
55 - Then I should see "There is no such page"  
56 -  
57 - Scenario: block access to chat for guest users  
58 - Given feature "xmpp_chat" is enabled on environment  
59 - When I go to chat  
60 - Then I should be on login page  
61 -  
62 - @selenium  
63 - Scenario: open chat in a new window  
64 - Given feature "xmpp_chat" is enabled on environment  
65 - And I am logged in as "tame"  
66 - When I follow "Open chat"  
67 - And I select window "noosfero_chat"  
68 - Then I should see "Chat - Colivre.net - Friends online (0)"  
69 -  
70 - @selenium  
71 - Scenario: open chat with an online user in a new window  
72 - Given the profile "tame" has no blocks  
73 - And feature "xmpp_chat" is enabled on environment  
74 - And I am logged in as "tame"  
75 - And I go to tame's profile  
76 - When I follow "chat-online-users-title"  
77 - And I follow "Maria Silva"  
78 - And I select window "noosfero_chat"  
79 - Then I should see "Chat - Colivre.net - Friends online (0)"  
80 -  
81 - @selenium  
82 - Scenario: chat starts disconnected by default  
83 - Given feature "xmpp_chat" is enabled on environment  
84 - And I am logged in as "tame"  
85 - When I follow "Open chat"  
86 - And I select window "noosfero_chat"  
87 - Then I should see "Offline" within "a"  
88 -  
89 - @selenium  
90 - Scenario: view options to change my chat status through menu  
91 - Given feature "xmpp_chat" is enabled on environment  
92 - And I am logged in as "tame"  
93 - And I follow "Open chat"  
94 - When I select window "noosfero_chat"  
95 - Then "Online" should not be visible within "#user-status"  
96 - And "Busy" should not be visible within "#user-status"  
97 - And "Sign out of chat" should not be visible within "#user-status"  
98 - When I follow "Offline"  
99 - Then "Online" should be visible within "#user-status"  
100 - And "Busy" should be visible within "#user-status"  
101 - And "Sign out of chat" should be visible within "#user-status"  
102 -  
103 - @selenium  
104 - Scenario: link to open chatroom of a community  
105 - Given the following communities  
106 - | identifier | name |  
107 - | autoramas | Autoramas |  
108 - And "Tame" is a member of "Autoramas"  
109 - And feature "xmpp_chat" is enabled on environment  
110 - And I am logged in as "tame"  
111 - When I go to autoramas's profile  
112 - Then I should see "Enter chat room"  
113 -  
114 - @selenium  
115 - Scenario: not see link to open chatroom of a community if not a member  
116 - Given the following communities  
117 - | identifier | name |  
118 - | autoramas | Autoramas |  
119 - And feature "xmpp_chat" is enabled on environment  
120 - And I am logged in as "tame"  
121 - When I go to autoramas's profile  
122 - Then I should not see "Enter chat room" within "a"  
123 -  
124 - @selenium  
125 - Scenario: not see link to open chatroom of a community if xmpp_chat disabled  
126 - Given the following communities  
127 - | identifier | name |  
128 - | autoramas | Autoramas |  
129 - And "Tame" is a member of "Autoramas"  
130 - And I am logged in as "tame"  
131 - When I go to autoramas's profile  
132 - Then I should not see "Enter chat room" within "a"  
133 -  
134 - @selenium  
135 - Scenario: open chatroom of a community in a new window  
136 - Given feature "xmpp_chat" is enabled on environment  
137 - And the following communities  
138 - | identifier | name |  
139 - | autoramas | Autoramas |  
140 - And "Tame" is a member of "Autoramas"  
141 - And I am logged in as "tame"  
142 - When I go to autoramas's profile  
143 - And I follow "Enter chat room"  
144 - And I select window "noosfero_chat"  
145 - Then I should see "Chat - Colivre.net - Friends online (0)"  
features/edit_profile.feature
@@ -27,44 +27,3 @@ Feature: edit profile @@ -27,44 +27,3 @@ Feature: edit profile
27 And I press "Save" 27 And I press "Save"
28 Then I should not see "Birth date is invalid" 28 Then I should not see "Birth date is invalid"
29 And I should not see "Birth date is mandatory" 29 And I should not see "Birth date is mandatory"
30 -  
31 - @selenium  
32 - Scenario: Alert about url change  
33 - Given the following community  
34 - | identifier | name | owner |  
35 - | o-rappa | O Rappa | joao |  
36 - And feature "enable_organization_url_change" is enabled on environment  
37 - And I go to o-rappa's control panel  
38 - When I follow "Community Info and settings"  
39 - Then I should not see "WARNING" within "#identifier-change-confirmation"  
40 - And I fill in "Address" with "banda-o-rappa"  
41 - When I leave the "#profile_data_identifier" field  
42 - Then I should see "WARNING" within "#identifier-change-confirmation"  
43 -  
44 - @selenium  
45 - Scenario: Confirm url change  
46 - Given the following community  
47 - | identifier | name | owner |  
48 - | o-rappa | O Rappa | joao |  
49 - And feature "enable_organization_url_change" is enabled on environment  
50 - And I go to o-rappa's control panel  
51 - And I follow "Community Info and settings"  
52 - And I fill in "Address" with "banda-o-rappa"  
53 - When I leave the "#profile_data_identifier" field  
54 - Then I should see "WARNING" within "#identifier-change-confirmation"  
55 - When I follow "Yes"  
56 - Then I should not see "WARNING" within "#identifier-change-confirmation"  
57 -  
58 - @selenium  
59 - Scenario: Cancel url change  
60 - Given the following community  
61 - | identifier | name | owner |  
62 - | o-rappa | O Rappa | joao |  
63 - And feature "enable_organization_url_change" is enabled on environment  
64 - And I go to o-rappa's control panel  
65 - And I follow "Community Info and settings"  
66 - And I fill in "Address" with "banda-o-rappa"  
67 - When I leave the "#profile_data_identifier" field  
68 - Then I should see "WARNING" within "#identifier-change-confirmation"  
69 - When I follow "No"  
70 - Then I should not see "WARNING" within "#identifier-change-confirmation"  
features/gallery_navigation.feature
@@ -1,86 +0,0 @@ @@ -1,86 +0,0 @@
1 -Feature: gallery_navigation  
2 - As a noosfero user  
3 - I want to navigate over image gallery  
4 -  
5 - Background:  
6 - Given the following users  
7 - | login |  
8 - | marciopunk |  
9 - And the following galleries  
10 - | owner | name |  
11 - | marciopunk | my-gallery |  
12 - | marciopunk | other-gallery |  
13 - And the following files  
14 - | owner | file | mime | parent |  
15 - | marciopunk | rails.png | image/png | my-gallery |  
16 - | marciopunk | rails.png | image/png | other-gallery |  
17 - | marciopunk | other-pic.jpg | image/jpeg | my-gallery |  
18 -  
19 - Scenario: provide link to go to next image  
20 - Given I am on /marciopunk/my-gallery/other-pic.jpg?view=true  
21 - Then I should see "Next »"  
22 -  
23 - @selenium  
24 - Scenario: view next image when follow next link  
25 - Given I am on /marciopunk/my-gallery/other-pic.jpg?view=true  
26 - When I follow "Next »"  
27 - Then I should see "rails.png" within ".title"  
28 -  
29 - Scenario: not link to next when in last image  
30 - When I am on /marciopunk/my-gallery/rails.png?view=true  
31 - Then I should see "« Previous" within ".gallery-navigation a"  
32 - And I should not see "Next »" within ".gallery-navigation a"  
33 -  
34 - Scenario: provide link to go to previous image  
35 - Given I am on /marciopunk/my-gallery/other-pic.jpg?view=true  
36 - Then I should see "« Previous"  
37 -  
38 - @selenium  
39 - Scenario: view previous image when follow previous link  
40 - Given I am on /marciopunk/my-gallery/rails.png?view=true  
41 - When I follow "« Previous"  
42 - Then I should see "other-pic.jpg" within ".title"  
43 -  
44 - Scenario: not link to previous when in first image  
45 - When I am on /marciopunk/my-gallery/other-pic.jpg?view=true  
46 - Then I should see "Next »" within ".gallery-navigation a"  
47 - And I should not see "« Previous" within ".gallery-navigation a"  
48 -  
49 - Scenario: display number of current and total of images  
50 - Given I am on /marciopunk/my-gallery/other-pic.jpg?view=true  
51 - Then I should see "image 1 of 2" within ".gallery-navigation"  
52 -  
53 - Scenario: increment current number when follow next  
54 - Given I am on /marciopunk/my-gallery/other-pic.jpg?view=true  
55 - Then I should see "image 1 of 2" within ".gallery-navigation"  
56 - When I follow "Next »"  
57 - Then I should see "image 2 of 2" within ".gallery-navigation"  
58 -  
59 - Scenario: decrement current number when follow next  
60 - Given I am on /marciopunk/my-gallery/rails.png?view=true  
61 - Then I should see "image 2 of 2" within ".gallery-navigation"  
62 - When I follow "« Previous"  
63 - Then I should see "image 1 of 2" within ".gallery-navigation"  
64 -  
65 - Scenario: provide button to go back to gallery  
66 - Given I am on /marciopunk/my-gallery/rails.png?view=true  
67 - Then I should see "Go back to my-gallery"  
68 - When I follow "Go back to my-gallery"  
69 - Then I should be on /marciopunk/my-gallery  
70 -  
71 - # Looking for page title is problematic on selenium since it considers the  
72 - # title to be invibible. Checkout some information about this:  
73 - # * https://github.com/jnicklas/capybara/issues/863  
74 - # * https://github.com/jnicklas/capybara/pull/953  
75 - @selenium  
76 - Scenario: image title in window title  
77 - Given I am logged in as "marciopunk"  
78 - When I go to /marciopunk/other-gallery/rails.png?view=true  
79 - Then I should see "rails.png" within any "h1"  
80 -# And the page title should be "rails.png"  
81 - And I follow "Edit"  
82 - And I fill in "Title" with "Rails is cool"  
83 - And I press "Save"  
84 - When I go to /marciopunk/other-gallery/rails.png?view=true  
85 - Then I should see "Rails is cool" within any "h1"  
86 - #Then the page title should be "Rails is cool"  
features/highlights_block.feature
@@ -1,44 +0,0 @@ @@ -1,44 +0,0 @@
1 -Feature: Edit Highlight Block  
2 - As a user  
3 - I want to edit the highlight block  
4 -  
5 - Background:  
6 - Given I am on the homepage  
7 - And the following users  
8 - | login | name |  
9 - | jose | Jose Silva |  
10 - And I am logged in as "jose"  
11 -  
12 - @selenium  
13 - Scenario: Add new highlight  
14 - Given I follow "Control panel"  
15 - And I follow "Edit sideboxes"  
16 - And I follow "Add a block"  
17 - And I choose "Highlights"  
18 - And I press "Add"  
19 - And I follow "Edit" within ".highlights-block"#Need to hover the mouse on the box  
20 - And I follow "New highlight"  
21 - And I fill in "block_images__address" with "/"  
22 - And I fill in "block_images__position" with "0"  
23 - And I fill in "block_images__title" with "test highlights"  
24 - And I press "Save"  
25 - And I follow "Edit" within ".highlights-block"  
26 - Then I should see "Title"  
27 -  
28 - @selenium-fixme  
29 - Scenario: Remove one saved highlight  
30 - Given I follow "Control panel"  
31 - And I follow "Edit sideboxes"  
32 - And I follow "Add a block"  
33 - And I choose "Highlights"  
34 - And I press "Add"  
35 - And I follow "Edit" within ".highlights-block"  
36 - And I follow "New highlight"  
37 - And I fill in "block_images__address" with "/"  
38 - And I fill in "block_images__position" with "0"  
39 - And I fill in "block_images__title" with "test highlights"#Need to hover the mouse on the box  
40 - And I press "Save"  
41 - And I follow "Edit" within ".highlights-block"  
42 - And I follow "" within ".delete-highlight"  
43 - And I confirm the browser dialog  
44 - Then I should not see "Title"  
45 \ No newline at end of file 0 \ No newline at end of file
features/http_caching.feature
@@ -1,69 +0,0 @@ @@ -1,69 +0,0 @@
1 -Feature: HTTP caching  
2 -  
3 - As a sysdamin  
4 - I want Noosfero to provide appropriate cache headers  
5 - So that Varnish can serve content from the cache, everything works faster and everyone is happy  
6 -  
7 - Background:  
8 - Given the following user  
9 - | login | name |  
10 - | joao | João Silva |  
11 -  
12 - Scenario: home page, default configuration  
13 - When I go to the homepage  
14 - Then the response should be valid for 5 minutes  
15 - And the cache should be public  
16 -  
17 - Scenario: home page, custom configuration  
18 - Given the following environment configuration  
19 - | home_cache_in_minutes | 10 |  
20 - When I go to the homepage  
21 - Then the response should be valid for 10 minutes  
22 -  
23 - Scenario: search results, default configuration  
24 - Given I am on the search page  
25 - When I fill in "query" with "anything"  
26 - And I press "Search"  
27 - Then the response should be valid for 15 minutes  
28 -  
29 - Scenario: search results, custom configuration  
30 - Given the following environment configuration  
31 - | general_cache_in_minutes | 90 |  
32 - When I go to the search page  
33 - And I fill in "query" with "anything"  
34 - And I press "Search"  
35 - Then the response should be valid for 90 minutes  
36 -  
37 - Scenario: profile pages, default configuaration  
38 - When I go to joao's homepage  
39 - Then the response should be valid for 15 minutes  
40 -  
41 - Scenario: profile pages, custom configuration  
42 - Given the following environment configuration  
43 - | profile_cache_in_minutes | 90 |  
44 - When I go to joao's homepage  
45 - Then the response should be valid for 90 minutes  
46 -  
47 - Scenario: account controller should not be cached at all  
48 - When I go to /account/login  
49 - Then there must be no cache at all  
50 -  
51 - Scenario: profile administration  
52 - Given I am logged in as "joao"  
53 - When I go to joao's control panel  
54 - Then there must be no cache at all  
55 -  
56 - Scenario: environment administration  
57 - Given I am logged in as admin  
58 - When I go to /admin  
59 - Then there must be no cache at all  
60 -  
61 - Scenario: logged in user in the homepage  
62 - Given I am logged in as "joao"  
63 - When I go to the homepage  
64 - Then there must be no cache at all  
65 -  
66 - Scenario: logged in user in a profile page  
67 - Given I am logged in as "joao"  
68 - When I go to /joao  
69 - Then there must be no cache at all  
features/manage_inputs.feature
@@ -1,247 +0,0 @@ @@ -1,247 +0,0 @@
1 -Feature: manage inputs  
2 - As an enterprise owner  
3 - I want to manage my product's inputs  
4 -  
5 - Background:  
6 - Given the following users  
7 - | login | name |  
8 - | joaosilva | Joao Silva |  
9 - And the following enterprises  
10 - | identifier | owner | name | enabled |  
11 - | redemoinho | joaosilva | Rede Moinho | true |  
12 - Given the following product_category  
13 - | name |  
14 - | Music |  
15 - And the following product_categories  
16 - | name | parent |  
17 - | Rock | music |  
18 - | CD Player | music |  
19 - And the following product  
20 - | owner | category | name |  
21 - | redemoinho | rock | Abbey Road |  
22 - And feature "products_for_enterprises" is enabled on environment  
23 - And the following units  
24 - | singular | plural |  
25 - | Meter | Meters |  
26 - | Litre | Litres |  
27 -  
28 - @selenium  
29 - Scenario: add first input to a product  
30 - Given I am logged in as "joaosilva"  
31 - When I go to Rede Moinho's page of product Abbey Road  
32 - And I follow "Inputs"  
33 - Then I should not see "Add new input or raw material"  
34 - And I follow "Add the inputs or raw material used by this product"  
35 - And I select "Music »" from "category_id" within "#categories_container_level0"  
36 - And I select "Rock" from "category_id" within "#categories_container_level1"  
37 - And I press "Save and continue"  
38 - Then I should see "Rock"  
39 -  
40 - @selenium  
41 - Scenario: add input to a product that already has inputs  
42 - Given the following input  
43 - | product | category |  
44 - | Abbey Road | music |  
45 - And I am logged in as "joaosilva"  
46 - When I go to Rede Moinho's page of product Abbey Road  
47 - And I follow "Inputs"  
48 - And I should not see "Add the inputs or raw material used by this product"  
49 - And I follow "Add new input or raw material"  
50 - And I select "Music »" from "category_id" within "#categories_container_level0"  
51 - And I select "Rock" from "category_id" within "#categories_container_level1"  
52 - And I press "Save and continue"  
53 - Then I should see "Rock"  
54 -  
55 - @selenium  
56 - Scenario: cancel addition of a product input  
57 - Given I am logged in as "joaosilva"  
58 - When I go to Rede Moinho's page of product Abbey Road  
59 - And I follow "Inputs"  
60 - And I follow "Add the inputs or raw material used by this product"  
61 - And I should see "Cancel" within "#categories_selection_actionbar"  
62 - And I follow "Cancel" within "#categories_selection_actionbar"  
63 - Then I should see "Abbey Road"  
64 - And I should see "Add the inputs or raw material used by this product"  
65 -  
66 - Scenario: show input name and link to add details  
67 - Given the following input  
68 - | product | category |  
69 - | Abbey Road | music |  
70 - And I am logged in as "joaosilva"  
71 - When I go to Rede Moinho's page of product Abbey Road  
72 - And I follow "Inputs and raw material"  
73 - Then I should see "Music" within ".input-name"  
74 - And I should see "Click here to add price and the amount used"  
75 -  
76 - Scenario: Not show input edit button when dont have details yet  
77 - Given the following input  
78 - | product | category |  
79 - | Abbey Road | music |  
80 - And I am logged in as "joaosilva"  
81 - When I go to Rede Moinho's page of product Abbey Road  
82 - And I follow "Inputs and raw material"  
83 - Then I should not see "Edit" within ".input-item"  
84 -  
85 - Scenario: Show button to edit input  
86 - Given the following input  
87 - | product | category | price_per_unit |  
88 - | Abbey Road | music | 10.0 |  
89 - And I am logged in as "joaosilva"  
90 - When I go to Rede Moinho's page of product Abbey Road  
91 - And I follow "Inputs and raw material"  
92 - Then I should see "Edit" within ".input-item"  
93 -  
94 - @selenium-fixme  
95 - Scenario: Order inputs by position  
96 - Given the following product_categories  
97 - | name |  
98 - | Instrumental |  
99 - And the following inputs  
100 - | product | category | position |  
101 - | Abbey Road | Instrumental | 2 |  
102 - | Abbey Road | Rock | 1 |  
103 - | Abbey Road | CD Player | 3 |  
104 - And I am logged in as "joaosilva"  
105 - When I go to Rede Moinho's page of product Abbey Road  
106 - And I follow "Inputs"  
107 - Then I should see "Rock" above of "Instrumental"  
108 - And I should see "Instrumental" above of "CD Player"  
109 -  
110 - @selenium  
111 - Scenario: Save price of input  
112 - Given the following input  
113 - | product | category |  
114 - | Abbey Road | music |  
115 - And I am logged in as "joaosilva"  
116 - When I go to Rede Moinho's page of product Abbey Road  
117 - And I follow "Inputs"  
118 - Then I should see "Music"  
119 - When I follow "Click here to add price and the amount used"  
120 - And I should see "Price"  
121 - And I fill in "Price" with "10.50"  
122 - And I press "Save"  
123 - Then I should not see "Save"  
124 -  
125 - @selenium  
126 - Scenario: Update label of input price with selected unit  
127 - Given the following input  
128 - | product | category |  
129 - | Abbey Road | music |  
130 - And I am logged in as "joaosilva"  
131 - When I go to Rede Moinho's page of product Abbey Road  
132 - And I follow "Inputs"  
133 - And I follow "Click here to add price and the amount used"  
134 - And I should not see "Price by Meter ($)"  
135 - When I select "Meter" from "input_unit_id" within ".edit_input"  
136 - Then I should see "Price by Meter ($)"  
137 -  
138 - @selenium  
139 - Scenario: Save all price details of input  
140 - Given the following input  
141 - | product | category |  
142 - | Abbey Road | music |  
143 - And I am logged in as "joaosilva"  
144 - When I go to Rede Moinho's page of product Abbey Road  
145 - And I follow "Inputs"  
146 - And I follow "Click here to add price and the amount used"  
147 - And I fill in "Amount used" with "2.5"  
148 - And I fill in "Price" with "11.50"  
149 - And I select "Meter" from "input_unit_id" within ".edit_input"  
150 - And I press "Save"  
151 - Then I should see "2.5"  
152 - And I should see "Meter"  
153 - And I should not see "$ 11.50"  
154 -  
155 - @selenium  
156 - Scenario: Save and then edit price details of input  
157 - Given the following input  
158 - | product | category |  
159 - | Abbey Road | music |  
160 - And I am logged in as "joaosilva"  
161 - When I go to Rede Moinho's page of product Abbey Road  
162 - And I follow "Inputs"  
163 - And I follow "Click here to add price and the amount used"  
164 - And I fill in "Amount used" with "2.5"  
165 - And I fill in "Price" with "11.50"  
166 - And I select "Meter" from "input_unit_id" within ".edit_input"  
167 - And I press "Save"  
168 - Then I should see "2.5"  
169 - And I should see "Meter"  
170 - When I follow "Edit" within ".input-details"  
171 - And I fill in "Amount used" with "3.0"  
172 - And I fill in "Price" with "23.31"  
173 - And I select "Litre" from "input_unit_id" within ".edit_input"  
174 - And I press "Save"  
175 - Then I should see "3"  
176 - And I should see "Litre"  
177 -  
178 - @selenium  
179 - Scenario: Cancel edition of a input  
180 - Given the following input  
181 - | product | category |  
182 - | Abbey Road | music |  
183 - And I am logged in as "joaosilva"  
184 - When I go to Rede Moinho's page of product Abbey Road  
185 - And I follow "Inputs"  
186 - And I follow "Click here to add price and the amount used"  
187 - Then I should see "Cancel"  
188 - And I should see "Amount used"  
189 - And I should see "Price"  
190 - And I should see "This input or raw material inpact on the final price of the product?"  
191 - When I follow "Cancel" within ".edit_input"  
192 - Then I should see "Click here to add price and the amount used"  
193 -  
194 - @selenium  
195 - Scenario: Cancel edition of an input then edit again  
196 - Given the following input  
197 - | product | category | price_per_unit | unit |  
198 - | Abbey Road | music | 10.0 | Meter |  
199 - And I am logged in as "joaosilva"  
200 - When I go to Rede Moinho's page of product Abbey Road  
201 - And I follow "Inputs"  
202 - And I follow "Edit" within ".input-details"  
203 - And I should see "Cancel" within ".edit_input"  
204 - And I follow "Cancel" within ".edit_input"  
205 - And I follow "Edit" within ".input-details"  
206 - Then I should see "Amount used"  
207 - And I should see "Price by Meter"  
208 -  
209 - @selenium  
210 - Scenario: remove input  
211 - Given the following input  
212 - | product | category |  
213 - | Abbey Road | rock |  
214 - And I am logged in as "joaosilva"  
215 - And I go to Rede Moinho's page of product Abbey Road  
216 - And I follow "Inputs"  
217 - Then I should see "Rock"  
218 - And I should not see "Add the inputs or raw material used by this product"  
219 - When I follow "Remove"  
220 - And I confirm the browser dialog  
221 - Then I should see "Add the inputs or raw material used by this product"  
222 -  
223 - @selenium-fixme  
224 - Scenario: Order input list  
225 - Given the following product_category  
226 - | name |  
227 - | Movie |  
228 - And the following product  
229 - | owner | category | name |  
230 - | redemoinho | Movie | Ramones |  
231 - And the following inputs  
232 - | product | category |  
233 - | Ramones | Rock |  
234 - | Ramones | Music |  
235 - | Ramones | CD Player |  
236 - And I am logged in as "joaosilva"  
237 - When I go to Rede Moinho's page of product Ramones  
238 - And I follow "Inputs"  
239 - Then I should see "Rock" above of "Music"  
240 - And I should see "Music" above of "CD Player"  
241 - When I drag "Rock" to "Music"  
242 - Then I should see "Music" above of "Rock"  
243 - And I should see "Rock" above of "CD Player"  
244 - When I follow "Back to the product listing"  
245 - And I go to Rede Moinho's page of product Ramones  
246 - Then I should see "Music" above of "Rock"  
247 - And I should see "Rock" above of "CD Player"  
features/manage_product_price_details.feature
@@ -1,179 +0,0 @@ @@ -1,179 +0,0 @@
1 -Feature: manage product price details  
2 - As an enterprise owner  
3 - I want to manage the details of product's price  
4 -  
5 - Background:  
6 - Given the following users  
7 - | login | name |  
8 - | joaosilva | Joao Silva |  
9 - And the following enterprises  
10 - | identifier | owner | name | enabled |  
11 - | redemoinho | joaosilva | Rede Moinho | true |  
12 - Given the following product_category  
13 - | name |  
14 - | Music |  
15 - And the following product_categories  
16 - | name | parent |  
17 - | Rock | music |  
18 - | CD Player | music |  
19 - And the following product  
20 - | owner | category | name | price |  
21 - | redemoinho | rock | Abbey Road | 80.0 |  
22 - And feature "products_for_enterprises" is enabled on environment  
23 - And the following inputs  
24 - | product | category | price_per_unit | amount_used |  
25 - | Abbey Road | Rock | 10.0 | 2 |  
26 - | Abbey Road | CD Player | 20.0 | 2 |  
27 - And the following production cost  
28 - | name | owner |  
29 - | Taxes | environment |  
30 - And I am logged in as "joaosilva"  
31 -  
32 - @selenium  
33 - Scenario: list total value of inputs as price details  
34 - Given I go to Rede Moinho's page of product Abbey Road  
35 - And I follow "Price composition"  
36 - And I follow "Describe here the cost of production"  
37 - Then I should see "Inputs"  
38 - And I should see "60.0" within ".inputs-cost"  
39 -  
40 - @selenium  
41 - Scenario: return to product after save  
42 - Given I go to Rede Moinho's page of product Abbey Road  
43 - And I follow "Price composition"  
44 - And I follow "Describe here the cost of production"  
45 - And I press "Save"  
46 - Then I should be on Rede Moinho's page of product Abbey Road  
47 -  
48 - @selenium  
49 - Scenario: add first item on price details  
50 - Given I go to Rede Moinho's page of product Abbey Road  
51 - And I follow "Price composition"  
52 - And I follow "Describe here the cost of production"  
53 - And I follow "New cost"  
54 - And I select "Taxes" from "price_details__production_cost_id" within "#display-product-price-details"  
55 - And I fill in "$" with "5.00"  
56 - And I leave the "#price_details__price" field  
57 - And I press "Save"  
58 - Then I should not see "Save"  
59 - And I should see "Describe here the cost of production"  
60 -  
61 - @selenium  
62 - Scenario: edit a production cost  
63 - Given the following production cost  
64 - | name | owner |  
65 - | Energy | environment |  
66 - When I go to Rede Moinho's page of product Abbey Road  
67 - And I follow "Price composition"  
68 - And I follow "Describe here the cost of production"  
69 - And I follow "New cost"  
70 - And I select "Taxes" from "price_details__production_cost_id" within "#display-product-price-details"  
71 - And I fill in "$" with "20.00"  
72 - And I leave the ".price-details-price" field  
73 - And I press "Save"  
74 - Then I should not see "Save"  
75 - And I should see "Taxes" within "#display-price-details"  
76 - When I follow "Describe here the cost of production"  
77 - And I select "Energy" from "price_details__production_cost_id" within "#display-product-price-details"  
78 - And I leave the "#price_details__price" field  
79 - And I press "Save"  
80 - And I should not see "Taxes" within "#display-price-details"  
81 - And I should see "Energy" within "#display-price-details"  
82 -  
83 - Scenario: not display price composition if product does not have input  
84 - Given the following product  
85 - | owner | category | name |  
86 - | redemoinho | rock | Yellow Submarine |  
87 - And the following user  
88 - | login | name |  
89 - | mariasouza | Maria Souza |  
90 - And I am logged in as "mariasouza"  
91 - When I go to Rede Moinho's page of product Yellow Submarine  
92 - Then I should not see "Price composition"  
93 -  
94 - Scenario: not display price composition if price is not fully described  
95 - Given I am not logged in  
96 - And I go to Rede Moinho's page of product Abbey Road  
97 - Then I should not see "Price composition"  
98 -  
99 - @selenium  
100 - Scenario: display price details if price is fully described  
101 - Given I go to Rede Moinho's page of product Abbey Road  
102 - And I follow "Price composition"  
103 - And I follow "Describe here the cost of production"  
104 - And I follow "New cost"  
105 - And I select "Taxes" from "price_details__production_cost_id" within "#display-product-price-details"  
106 - And I fill in "$" with "20.00"  
107 - And I press "Save"  
108 - And I go to Rede Moinho's page of product Abbey Road  
109 - Then I should see "Inputs" within ".price-detail-name"  
110 - And I should see "60.0" within ".price-detail-price"  
111 -  
112 - @selenium  
113 - Scenario: create a new cost clicking on select  
114 - Given I go to Rede Moinho's page of product Abbey Road  
115 - And I follow "Price composition"  
116 - And I follow "Describe here the cost of production"  
117 - And I follow "New cost"  
118 - And I select "Other cost" from "price_details__production_cost_id" within "#display-product-price-details"  
119 - And I want to add "Energy" as cost  
120 - And I fill in "$" with "10.00"  
121 - And I leave the "#price_details__price" field  
122 - And I press "Save"  
123 - When I follow "Describe here the cost of production"  
124 - Then I should see "Energy" within ".production-cost-selection"  
125 -  
126 - @selenium  
127 - Scenario: add created cost on new-cost-fields  
128 - Given I go to Rede Moinho's page of product Abbey Road  
129 - And I follow "Price composition"  
130 - And I follow "Describe here the cost of production"  
131 - And I follow "New cost"  
132 - And I select "Other cost" from "price_details__production_cost_id" within "#display-product-price-details"  
133 - And I want to add "Energy" as cost  
134 - Then I should see "Energy" within "#display-product-price-details"  
135 -  
136 - @selenium  
137 - Scenario: remove price detail  
138 - Given the following price detail  
139 - | product | production_cost | price |  
140 - | Abbey Road | Taxes | 20.0 |  
141 - And I go to Rede Moinho's page of product Abbey Road  
142 - And I follow "Price composition"  
143 - And I follow "Describe here the cost of production"  
144 - And I should see "Taxes" within "#manage-product-details-form"  
145 - When I follow "Remove" within "#manage-product-details-form"  
146 - And I confirm the browser dialog  
147 - And I press "Save"  
148 - And I follow "Describe here the cost of production"  
149 - Then I should not see "Taxes" within "#manage-product-details-form"  
150 -  
151 - Scenario: display progressbar  
152 - Given I go to Rede Moinho's page of product Abbey Road  
153 - And I follow "Price composition"  
154 - And I follow "Describe here the cost of production"  
155 - Then I should see "$ 60.00 of $ 80.00" within "#progressbar-text"  
156 -  
157 - @selenium  
158 - Scenario: update value on progressbar after addition of new cost  
159 - Given I go to Rede Moinho's page of product Abbey Road  
160 - And I follow "Price composition"  
161 - And I follow "Describe here the cost of production"  
162 - Then I should see "$ 60.00 of $ 80.00" within "#progressbar-text"  
163 - And I follow "New cost"  
164 - And I fill in "$" with "10.00"  
165 - And I leave the "#price_details__price" field  
166 - Then I should see "$ 70.00 of $ 80.00" within "#progressbar-text"  
167 -  
168 - @selenium  
169 - Scenario: update value on progressbar after editing an input  
170 - Given I go to Rede Moinho's page of product Abbey Road  
171 - And I follow "Price composition"  
172 - And I follow "Describe here the cost of production"  
173 - Then I should see "$ 60.00 of $ 80.00" within "#progressbar-text"  
174 - When I follow "Inputs"  
175 - And I follow "Edit" within ".input-details"  
176 - And I fill in "Price" with "23.31"  
177 - And I press "Save"  
178 - Then I follow "Price composition"  
179 - And I should see "$ 86.62 of $ 80.00" within "#progressbar-text"  
features/manage_products.feature
@@ -1,520 +0,0 @@ @@ -1,520 +0,0 @@
1 -Feature: manage products  
2 - As an enterprise owner  
3 - I want to manage my products  
4 -  
5 - Background:  
6 - Given the following users  
7 - | login | name |  
8 - | joaosilva | Joao Silva |  
9 - And the following enterprises  
10 - | identifier | owner | name | enabled |  
11 - | redemoinho | joaosilva | Rede Moinho | true |  
12 - And feature "products_for_enterprises" is enabled on environment  
13 -  
14 - Scenario: display "create new product" button  
15 - Given I am logged in as "joaosilva"  
16 - And I am on redemoinho's control panel  
17 - When I follow "Manage Products/Services"  
18 - Then I should see "New product or service"  
19 -  
20 - Scenario: paginate public listing products and services  
21 - Given the following product_category  
22 - | name |  
23 - | Bicycle |  
24 - And the following products  
25 - | owner | category | name | description | created_at |  
26 - | redemoinho | bicycle | Bike A | bicycle 1 | 2014-04-01 01:00:00 |  
27 - | redemoinho | bicycle | Bike B | bicycle 2 | 2014-04-01 02:00:00 |  
28 - | redemoinho | bicycle | Bike C | bicycle 3 | 2014-04-01 03:00:00 |  
29 - | redemoinho | bicycle | Bike D | bicycle 4 | 2014-04-01 04:00:00 |  
30 - | redemoinho | bicycle | Bike E | bicycle 5 | 2014-04-01 05:00:00 |  
31 - | redemoinho | bicycle | Bike F | bicycle 6 | 2014-04-01 06:00:00 |  
32 - | redemoinho | bicycle | Bike G | bicycle 7 | 2014-04-01 07:00:00 |  
33 - | redemoinho | bicycle | Bike H | bicycle 8 | 2014-04-01 08:00:00 |  
34 - | redemoinho | bicycle | Bike I | bicycle 9 | 2014-04-01 09:00:00 |  
35 - | redemoinho | bicycle | Bike J | bicycle 10 | 2014-04-01 10:00:00 |  
36 - | redemoinho | bicycle | Bike K | bicycle 11 | 2014-04-01 11:00:00 |  
37 - When I go to redemoinho's products page  
38 - Then I should see "Bike A" within "#product-list"  
39 - And I should see "Bike B" within "#product-list"  
40 - And I should see "Bike C" within "#product-list"  
41 - And I should see "Bike D" within "#product-list"  
42 - And I should see "Bike E" within "#product-list"  
43 - And I should see "Bike F" within "#product-list"  
44 - And I should not see "Bike G" within "#product-list"  
45 - And I should not see "Bike H" within "#product-list"  
46 - And I should not see "Bike I" within "#product-list"  
47 - And I should not see "Bike J" within "#product-list"  
48 - And I should not see "Bike K" within "#product-list"  
49 - When I follow "Next"  
50 - Then I should see "Bike G" within "#product-list"  
51 - Then I should see "Bike H" within "#product-list"  
52 - Then I should see "Bike I" within "#product-list"  
53 - Then I should see "Bike J" within "#product-list"  
54 - Then I should see "Bike K" within "#product-list"  
55 -  
56 - Scenario: listing products and services  
57 - Given I am logged in as "joaosilva"  
58 - And I am on redemoinho's control panel  
59 - And I follow "Manage Products/Services"  
60 - Then I should see "Listing products and services"  
61 -  
62 - Scenario: see button to back in categories hierarchy  
63 - Given I am logged in as "joaosilva"  
64 - And I am on redemoinho's control panel  
65 - And I follow "Manage Products/Services"  
66 - When I follow "New product or service"  
67 - Then I should see "Back to the product listing" link  
68 -  
69 - Scenario: see toplevel categories  
70 - Given the following product_categories  
71 - | name |  
72 - | Products |  
73 - | Services |  
74 - Given I am logged in as "joaosilva"  
75 - And I go to redemoinho's new product page  
76 - Then I should see "Products"  
77 - And I should see "Service"  
78 -  
79 - @selenium  
80 - Scenario: select a toplevel category and see subcategories  
81 - Given the following product_categories  
82 - | name |  
83 - | Products level0 |  
84 - And the following product_categories  
85 - | name | parent |  
86 - | Computers level1 | products-level0 |  
87 - | DVDs level1 | products-level0 |  
88 - Given I am logged in as "joaosilva"  
89 - And I go to redemoinho's new product page  
90 - And I select "Products level0 »" from "category_id" within "#categories_container_level0"  
91 - Then I should see "Computers level1"  
92 - And I should see "DVDs level1"  
93 -  
94 - @selenium  
95 - Scenario: hide subcategories when select other toplevel category  
96 - Given the following product_categories  
97 - | name |  
98 - | Products level0 |  
99 - | Services level0 |  
100 - And the following product_categories  
101 - | name | parent |  
102 - | Computers level1 | products-level0 |  
103 - | Software development level1 | services-level0 |  
104 - Given I am logged in as "joaosilva"  
105 - And I go to redemoinho's new product page  
106 - And I should not see /Computers level/  
107 - And I select "Products level0 »" from "category_id" within "#categories_container_wrapper"  
108 - And I should see /Computers level/  
109 - And I should not see /Software develop/  
110 - And I select "Services level0 »" from "category_id" within "#categories_container_wrapper"  
111 - Then I should see /Software develop/  
112 - And I should not see /Computers level/  
113 -  
114 - @selenium  
115 - Scenario: show hierarchy of categories  
116 - Given the following product_categories  
117 - | name |  
118 - | Products |  
119 - And the following product_category  
120 - | name | parent |  
121 - | Computers | products |  
122 - Given I am logged in as "joaosilva"  
123 - And I go to redemoinho's new product page  
124 - And I select "Products »" from "category_id" within "#categories_container_level0"  
125 - And I select "Computers" from "category_id" within "#categories_container_level1"  
126 - Then I should see "Products → Computers"  
127 -  
128 - @selenium  
129 - Scenario: show links in hierarchy of categories and not link current category  
130 - Given the following product_category  
131 - | name |  
132 - | Toplevel Product Categories |  
133 - Given the following product_category  
134 - | name | parent |  
135 - | Category Level 1 | toplevel-product-categories |  
136 - Given I am logged in as "joaosilva"  
137 - And I go to redemoinho's new product page  
138 - And I select "Toplevel Product Categories »" from "category_id" within "#categories_container_level0"  
139 - And I select "Category Level 1" from "category_id" within "#categories_container_level1"  
140 - Then I should see "Toplevel Product Categories" link  
141 - And I should not see "Category Level 1" link  
142 -  
143 - @selenium  
144 - Scenario: save button come initialy disabled  
145 - Given the following product_category  
146 - | name |  
147 - | Only for test |  
148 - And I am logged in as "joaosilva"  
149 - When I go to redemoinho's new product page  
150 - Then the "#save_and_continue" button should be disabled  
151 -  
152 - @selenium  
153 - Scenario: enable save button when select one category  
154 - Given I am logged in as "joaosilva"  
155 - And the following product_category  
156 - | name |  
157 - | Browsers (accept categories) |  
158 - When I go to redemoinho's new product page  
159 - And I select "Browsers (accept categories)" from "category_id" within "#categories_container_wrapper"  
160 - Then the "#save_and_continue" button should be enabled  
161 -  
162 - @selenium  
163 - Scenario: dont enable save button when select category with not accept products  
164 - Given the following product_category  
165 - | name | accept_products |  
166 - | Browsers | false |  
167 - Given I am logged in as "joaosilva"  
168 - When I go to redemoinho's new product page  
169 - And I select "Browsers" from "category_id" within "#categories_container_wrapper"  
170 - Then the "#save_and_continue" button should be disabled  
171 -  
172 - @selenium  
173 - Scenario: save product  
174 - Given the following product_category  
175 - | name |  
176 - | Bicycle |  
177 - Given I am logged in as "joaosilva"  
178 - When I go to redemoinho's new product page  
179 - And I select "Bicycle" from "category_id" within "#categories_container_wrapper"  
180 - And I press "Save and continue"  
181 - When I go to redemoinho's products page  
182 - And I follow "Bicycle" within "#product-list"  
183 - Then I should see "Bicycle" within "#show_product"  
184 - And I should see "Change category"  
185 -  
186 - Scenario: a user with permission can see edit links  
187 - Given the following product_category  
188 - | name |  
189 - | Bicycle |  
190 - And the following products  
191 - | owner | category | name | description |  
192 - | redemoinho | bicycle | Bike | Red bicycle |  
193 - And I am logged in as "joaosilva"  
194 - When I go to Rede Moinho's page of product Bike  
195 - Then I should see "Change category"  
196 - And I should see "Edit name"  
197 - And I should see "Edit description"  
198 - And I should see "Change image"  
199 -  
200 - Scenario: an allowed user will see a different button when has no description  
201 - Given the following product_category  
202 - | name |  
203 - | Bicycle |  
204 - And the following products  
205 - | owner | category | name |  
206 - | redemoinho | bicycle | Bike |  
207 - And I am logged in as "joaosilva"  
208 - When I go to Rede Moinho's page of product Bike  
209 - Then I should see "Change category"  
210 - And I should see "Edit name"  
211 - And I should see "Add some description to your product"  
212 - And I should see "Add price and other basic information"  
213 - And I should see "Change image"  
214 -  
215 - Scenario: an allowed user will see a different button when has no basic info  
216 - Given the following product_category  
217 - | name |  
218 - | Bicycle |  
219 - And the following products  
220 - | owner | category | name |  
221 - | redemoinho | bicycle | Bike |  
222 - And I am logged in as "joaosilva"  
223 - When I go to Rede Moinho's page of product Bike  
224 - Then I should see "Change category"  
225 - And I should see "Edit name"  
226 - And I should see "Add price and other basic information"  
227 - And I should see "Change image"  
228 -  
229 - Scenario: a not logged user cannot see edit links  
230 - Given I am not logged in  
231 - And the following product_category  
232 - | name |  
233 - | Bicycle |  
234 - And the following products  
235 - | owner | category | name | description |  
236 - | redemoinho | bicycle | Bike | Red bicycle |  
237 - When I go to Rede Moinho's page of product Bike  
238 - Then I should not see "Change category"  
239 - And I should not see "Edit name"  
240 - And I should not see "Edit description"  
241 - And I should not see "Edit basic information"  
242 - And I should not see "Change image"  
243 -  
244 - Scenario: a not allowed user cannot see edit links  
245 - Given the following users  
246 - | login | name |  
247 - | mariasantos | Maria Santos |  
248 - And the following product_category  
249 - | name |  
250 - | Bicycle |  
251 - And the following products  
252 - | owner | category | name | description |  
253 - | redemoinho | bicycle | Bike | Red bicycle |  
254 - And I am logged in as "mariasantos"  
255 - When I go to Rede Moinho's page of product Bike  
256 - Then I should not see "Change category"  
257 - And I should not see "Edit name"  
258 - And I should not see "Edit description"  
259 - And I should not see "Edit basic information"  
260 - And I should not see "Change image"  
261 -  
262 - @selenium  
263 - Scenario: edit name of a product  
264 - Given the following product_category  
265 - | name |  
266 - | Bicycle |  
267 - And the following products  
268 - | owner | category | name |  
269 - | redemoinho | bicycle | Bike |  
270 - And I am logged in as "joaosilva"  
271 - When I go to Rede Moinho's page of product Bike  
272 - And I follow "Edit name"  
273 - And I fill in "Red bicycle" for "product_name"  
274 - And I press "Save"  
275 - Then I should see "Red bicycle"  
276 - And I should be on Rede Moinho's page of product Red bicycle  
277 -  
278 - @selenium  
279 - Scenario: cancel edition of a product name  
280 - Given the following product_category  
281 - | name |  
282 - | Bicycle |  
283 - And the following products  
284 - | owner | category | name |  
285 - | redemoinho | bicycle | Bike |  
286 - And I am logged in as "joaosilva"  
287 - When I go to Rede Moinho's page of product Bike  
288 - And I follow "Edit name"  
289 - When I follow "Cancel"  
290 - Then I should see "Bike"  
291 -  
292 - @selenium  
293 - Scenario: edit category of a product  
294 - Given the following product_category  
295 - | name |  
296 - | Eletronics |  
297 - And the following product_categories  
298 - | name | parent |  
299 - | Computers | eletronics |  
300 - | DVDs | eletronics |  
301 - And the following products  
302 - | owner | category | name |  
303 - | redemoinho | computers | Generic pc |  
304 - And I am logged in as "joaosilva"  
305 - When I go to Rede Moinho's page of product Generic pc  
306 - And I follow "Change category"  
307 - And I select "Eletronics »" from "category_id" within "#categories_container_level0"  
308 - Then I select "DVDs" from "category_id" within "#categories_container_level1"  
309 - And I press "Save and continue"  
310 - When I go to Rede Moinho's page of product Generic pc  
311 - Then I should see "Eletronics → DVDs" within ".hierarchy-category"  
312 -  
313 - @selenium  
314 - Scenario: cancel edition of a product category  
315 - Given the following product_category  
316 - | name |  
317 - | Eletronics |  
318 - And the following product_categories  
319 - | name | parent |  
320 - | Computers | eletronics |  
321 - | DVDs | eletronics |  
322 - And the following products  
323 - | owner | category | name |  
324 - | redemoinho | computers | Generic pc |  
325 - And I am logged in as "joaosilva"  
326 - When I go to Rede Moinho's page of product Generic pc  
327 - And I follow "Change category"  
328 - When I follow "Back to product"  
329 - Then I should see "Eletronics → Computers"  
330 -  
331 -  
332 - @selenium  
333 - Scenario: edit image of a product  
334 - Given the following product_category  
335 - | name |  
336 - | Eletronics |  
337 - And the following product_categories  
338 - | name | parent |  
339 - | Computers | eletronics |  
340 - | DVDs | eletronics |  
341 - And the following products  
342 - | owner | category | name |  
343 - | redemoinho | computers | Generic pc |  
344 - And I am logged in as "joaosilva"  
345 - When I go to Rede Moinho's page of product Generic pc  
346 - And I follow "Change image"  
347 - When I follow "Cancel"  
348 - Then I should be on Rede Moinho's page of product Generic pc  
349 -  
350 - # FIXME Not working because of tinyMCE plus selenium  
351 - # @selenium  
352 - # Scenario: edit description of a product  
353 - # Given the following product_category  
354 - # | name |  
355 - # | Bicycle |  
356 - # And the following products  
357 - # | owner | category | name | description |  
358 - # | redemoinho | bicycle | Bike | A new red bicycle |  
359 - # And I am logged in as "joaosilva"  
360 - # When I go to Rede Moinho's page of product Bike  
361 - # Then I should see "A new red bicycle"  
362 - # And I follow "Edit basic information"  
363 - # And I type in tinyMCE field "Description" the text "An used red bicycle"  
364 - # And I press "Save"  
365 - # Then I should not see "A new red bicycle"  
366 - # And I should see "An used red bicycle"  
367 - # And I should be on Rede Moinho's page of product Bike  
368 -  
369 - @selenium  
370 - Scenario: cancel edition of a product description  
371 - Given the following product_category  
372 - | name |  
373 - | Bicycle |  
374 - And the following products  
375 - | owner | category | name | description |  
376 - | redemoinho | bicycle | Bike | A new red bicycle |  
377 - And I am logged in as "joaosilva"  
378 - When I go to Rede Moinho's page of product Bike  
379 - Then I should see "A new red bicycle"  
380 - And I follow "Edit description"  
381 - When I follow "Cancel"  
382 - Then I should see "A new red bicycle"  
383 - And I should be on Rede Moinho's page of product Bike  
384 -  
385 - @selenium  
386 - Scenario: Edit product category and save without select any category  
387 - Given the following product_category  
388 - | name |  
389 - | Eletronics |  
390 - And the following product_category  
391 - | name | parent |  
392 - | Computers | eletronics |  
393 - And the following products  
394 - | owner | category | name |  
395 - | redemoinho | computers | Generic pc |  
396 - And I am logged in as "joaosilva"  
397 - When I go to Rede Moinho's page of product Generic pc  
398 - And I follow "Change category"  
399 - And I press "Save and continue"  
400 - Then I should not see "Product category can't be blank"  
401 - When I go to Rede Moinho's page of product Generic pc  
402 - Then I should see "Eletronics → Computers" within ".hierarchy-category"  
403 -  
404 - And I should see "Generic pc"  
405 -  
406 - @selenium  
407 - Scenario: Scroll categories selection to right when editing  
408 - Given the following product_category  
409 - | name |  
410 - | Eletronics |  
411 - And the following product_category  
412 - | name | parent |  
413 - | Quantum Computers | eletronics |  
414 - And the following product_category  
415 - | name | parent |  
416 - | Laptops from Mars | Quantum Computers |  
417 - And the following product_category  
418 - | name | parent |  
419 - | Netbook from Venus | Laptops from Mars |  
420 - And the following product_category  
421 - | name | parent |  
422 - | Nanonote nanotech with long name | Netbook from Venus |  
423 - And the following products  
424 - | owner | category | name |  
425 - | redemoinho | Nanonote nanotech with long name | Generic pc |  
426 - And I am logged in as "joaosilva"  
427 - When I go to Rede Moinho's page of product Generic pc  
428 - And I follow "Change category"  
429 - Then "Netbook from Venus" should be visible within "#categories_container_wrapper"  
430 -  
431 - @selenium  
432 - Scenario: Truncate long category name in selection of category  
433 - Given the following product_category  
434 - | name |  
435 - | Super Quantum Computers with teraflops |  
436 - | Nanonote nanotech with long long name |  
437 - And the following product_category  
438 - | name | parent |  
439 - | Netbook Quantum | Super Quantum Computers with teraflops |  
440 - And I am logged in as "joaosilva"  
441 - When I go to redemoinho's new product page  
442 - Then I should see "Nanonote nanotech with long lo..."  
443 - And I should see "Super Quantum Computers with t... »"  
444 -  
445 - @selenium  
446 - Scenario: Edit unit of a product together your name  
447 - Given the following product_category  
448 - | name |  
449 - | Bicycle |  
450 - And the following products  
451 - | owner | category | name |  
452 - | redemoinho | bicycle | Bike |  
453 - And the following units  
454 - | singular | plural |  
455 - | Kilo | Kilos |  
456 - And I am logged in as "joaosilva"  
457 - When I go to Rede Moinho's page of product Bike  
458 - And I follow "Edit name and unit"  
459 - And I fill in "Red bicycle" for "product_name"  
460 - And I select "Kilo" from "product_unit_id" within "#product-name-form"  
461 - And I press "Save"  
462 - Then I should see "Red bicycle - kilo"  
463 -  
464 - @selenium  
465 - Scenario: Show info about unavailable product  
466 - Given the following product_category  
467 - | name |  
468 - | Bicycle |  
469 - And the following products  
470 - | owner | category | name |  
471 - | redemoinho | bicycle | Bike |  
472 - And I am logged in as "joaosilva"  
473 - When I go to Rede Moinho's page of product Bike  
474 - And I follow "Add price and other basic information"  
475 - And I fill in "10" for "product_price"  
476 - And I choose "No"  
477 - And I press "Save"  
478 - Then I should see "Product not available!"  
479 -  
480 - @selenium  
481 - Scenario: Add and remove some qualifiers  
482 - Given the following product_category  
483 - | name |  
484 - | Bicycle |  
485 - And the following products  
486 - | owner | category | name |  
487 - | redemoinho | bicycle | Bike |  
488 - And the following qualifiers  
489 - | name |  
490 - | Organic |  
491 - And the following certifiers  
492 - | name | qualifiers |  
493 - | Colivre | Organic |  
494 - And I am logged in as "joaosilva"  
495 - When I go to Rede Moinho's page of product Bike  
496 - And I follow "Add price and other basic information"  
497 - And I follow "Add new qualifier"  
498 - And I select "Organic" from "selected_qualifier" within "#product-qualifiers-list"  
499 - And I press "Save"  
500 - And I go to Rede Moinho's page of product Bike  
501 - Then I should see "Organic (Self declared)"  
502 - When I follow "Edit basic information"  
503 - And I follow "Delete qualifier"  
504 - And I press "Save"  
505 - And I go to Rede Moinho's page of product Bike  
506 - Then I should not see "Organic (Self declared)"  
507 -  
508 - @selenium  
509 - Scenario: Show checkbox to mark product as highlight  
510 - Given the following product_category  
511 - | name |  
512 - | Bicycle |  
513 - And the following products  
514 - | owner | category | name |  
515 - | redemoinho | bicycle | Bike |  
516 - And I am logged in as "joaosilva"  
517 - When I go to Rede Moinho's page of product Bike  
518 - And I follow "Add price and other basic information"  
519 - Then I should see "Highlight this product?"  
520 - And I check "Highlight this product?"  
features/my_network_block.feature
@@ -1,79 +0,0 @@ @@ -1,79 +0,0 @@
1 -Feature: my_network_block  
2 - As a blog owner  
3 - I want to see a summary of my network  
4 -  
5 - Background:  
6 - Given the following users  
7 - | login | name |  
8 - | joaosilva | Joao Silva |  
9 - And the following blocks  
10 - | owner | type |  
11 - | joaosilva | MyNetworkBlock |  
12 - | joaosilva | FriendsBlock |  
13 - And the following communities  
14 - | identifier | name | public_profile |  
15 - | public-community | Public Community | true |  
16 - And plugin FriendsBlock is enabled on environment  
17 -  
18 - @selenium  
19 - Scenario: display how many public/private communities I am member  
20 - Given I am logged in as "joaosilva"  
21 - And the following communities  
22 - | identifier | name | owner | public_profile |  
23 - | other-public-community | Other Public Community | joaosilva | true |  
24 - | private-community | Private Community | joaosilva | false |  
25 - And I am on joaosilva's homepage  
26 - And I should see "2 communities"  
27 - When I go to public-community's homepage  
28 - And I follow "Join"  
29 - And I go to joaosilva's homepage  
30 - Then I should see "3 communities"  
31 -  
32 - @selenium  
33 - Scenario: not display how many invisible communities I am member  
34 - Given I am logged in as "joaosilva"  
35 - And the following communities  
36 - | identifier | name | owner | visible |  
37 - | visible-community | Visible Community | joaosilva | true |  
38 - | not-visible-community | Not Visible Community | joaosilva | false |  
39 - And I am on joaosilva's homepage  
40 - And I should see "One community"  
41 - When I go to public-community's homepage  
42 - And I follow "Join"  
43 - And I go to joaosilva's homepage  
44 - Then I should see "2 communities"  
45 -  
46 - Scenario: display how many public/private friends I have  
47 - Given the following users  
48 - | login | name | public_profile |  
49 - | mariasilva | Maria Silva | true |  
50 - | josesilva | Jose Silva | false |  
51 - And the following blocks  
52 - | owner | type |  
53 - | mariasilva | FriendsBlock |  
54 - | josesilva | FriendsBlock |  
55 - And "joaosilva" is friend of "mariasilva"  
56 - And I am logged in as "joaosilva"  
57 - And I am on joaosilva's homepage  
58 - Then I should see "1 friend"  
59 - And "joaosilva" is friend of "josesilva"  
60 - When I go to joaosilva's homepage  
61 - Then I should see "2 friends"  
62 -  
63 - Scenario: not display how many invisible friends I have  
64 - Given the following users  
65 - | login | name |  
66 - | mariasilva | Maria Silva |  
67 - | josesilva | Jose Silva |  
68 - And the following blocks  
69 - | owner | type |  
70 - | mariasilva | FriendsBlock |  
71 - | josesilva | FriendsBlock |  
72 - And "josesilva" is invisible  
73 - And "joaosilva" is friend of "mariasilva"  
74 - And I am logged in as "joaosilva"  
75 - When I go to joaosilva's homepage  
76 - Then I should see "1 friend"  
77 - And "joaosilva" is friend of "josesilva"  
78 - When I go to joaosilva's homepage  
79 - Then I should see "1 friend"  
features/profile_tags.feature
@@ -1,20 +0,0 @@ @@ -1,20 +0,0 @@
1 -Feature: profile tags  
2 - As a Noosfero user  
3 - I want to to view content tagged  
4 - So that I can follow the subjects I care about  
5 -  
6 - Background:  
7 - Given the following users  
8 - | login |  
9 - | terceiro |  
10 - And the following articles  
11 - | owner | name | body | tag_list |  
12 - | terceiro | text 1 | text 1 content | tag1, tag2 |  
13 - | terceiro | text 2 | text 2 content | tag1, tag3 |  
14 -  
15 - Scenario: tag feed  
16 - When I go to terceiro's profile  
17 - And I follow "tag1"  
18 - And I follow "Feed for this tag"  
19 - Then I should see "text 1"  
20 - And I should see "text 2"  
features/session_and_cookies_handling.feature
@@ -1,40 +0,0 @@ @@ -1,40 +0,0 @@
1 -Feature: session and cookies handling  
2 -  
3 - As a Noosfero system administrator  
4 - I want Noosfero to manage well it usage of sessions and cookies  
5 - So that we can use HTTP caching effectively  
6 -  
7 - @fixme  
8 - Scenario: home page, logged in  
9 - Given the following users  
10 - | login |  
11 - | joaosilva |  
12 - When I am logged in as "joaosilva"  
13 - And I go to the homepage  
14 - Then there must be a cookie "_noosfero_session"  
15 -  
16 - Scenario: home page, not logged in  
17 - When I go to the homepage  
18 - Then there must be no cookies  
19 -  
20 - @fixme  
21 - Scenario: user_data, not logged in  
22 - When I make a AJAX request to the user data path  
23 - Then there must be no cookies  
24 -  
25 - @fixme  
26 - Scenario: user_data, logged in  
27 - Given I am logged in as admin  
28 - When I make a AJAX request to the user data path  
29 - Then there must be a cookie "_noosfero_session"  
30 -  
31 - # FIXME for some reason I could not test this scenario, although manual tests  
32 - # indicate this works!  
33 - # Scenario: logout  
34 - # Given the following users  
35 - # | login |  
36 - # | joao |  
37 - # When I am logged in as "joao"  
38 - # And I log off  
39 - # And I go to the homepage  
40 - # Then there must be no cookies  
features/signup.feature
@@ -278,28 +278,6 @@ Feature: signup @@ -278,28 +278,6 @@ Feature: signup
278 Then "José da Silva" should be a member of "Free Software" 278 Then "José da Silva" should be a member of "Free Software"
279 279
280 @selenium 280 @selenium
281 - Scenario: join community on direct signup  
282 - Given the following users  
283 - | login | name |  
284 - | mariasilva | Maria Silva |  
285 - And the following communities  
286 - | name | identifier | owner |  
287 - | Free Software | freesoftware | mariasilva |  
288 - And feature "skip_new_user_email_confirmation" is enabled on environment  
289 - And I am on /freesoftware  
290 - When I follow "Join"  
291 - And I follow "New user"  
292 - And I fill in the following within ".no-boxes":  
293 - | e-Mail | josesilva@example.com |  
294 - | Username | josesilva |  
295 - | Password | secret |  
296 - | Password confirmation | secret |  
297 - | Full name | José da Silva |  
298 - And wait for the captcha signup time  
299 - And I press "Create my account"  
300 - Then "José da Silva" should be a member of "Free Software"  
301 -  
302 - @selenium  
303 Scenario: user registration is moderated by admin 281 Scenario: user registration is moderated by admin
304 Given feature "admin_must_approve_new_users" is enabled on environment 282 Given feature "admin_must_approve_new_users" is enabled on environment
305 And feature "skip_new_user_email_confirmation" is disabled on environment 283 And feature "skip_new_user_email_confirmation" is disabled on environment
@@ -349,4 +327,4 @@ Feature: signup @@ -349,4 +327,4 @@ Feature: signup
349 And I fill in "Username / Email" with "teste" 327 And I fill in "Username / Email" with "teste"
350 And I fill in "Password" with "123456" 328 And I fill in "Password" with "123456"
351 And I press "Log in" 329 And I press "Log in"
352 - Then I should not see "teste"  
353 \ No newline at end of file 330 \ No newline at end of file
  331 + Then I should not see "teste"
features/step_definitions/http_caching_steps.rb
@@ -1,21 +0,0 @@ @@ -1,21 +0,0 @@
1 -Then /^the response should be valid for (.+) minutes$/ do |n|  
2 - page.response_headers['Cache-Control'].split(/,\s*/).should include("max-age=#{n.to_i * 60}")  
3 -end  
4 -  
5 -Then /^the cache should be public/ do  
6 - page.response_headers['Cache-Control'].split(/,\s*/).should include("public")  
7 -end  
8 -  
9 -Then /^there must be no cache at all$/ do  
10 - parts = page.response_headers['Cache-Control'].split(/,\s*/)  
11 - parts.should include('must-revalidate')  
12 - parts.should include('max-age=0')  
13 -end  
14 -  
15 -Then 'there must be no cookies' do  
16 - cookies.to_hash.should == {}  
17 -end  
18 -  
19 -Then /^there must be a cookie "(.+)"$/ do |cookie_name|  
20 - cookies.keys.should include(cookie_name)  
21 -end  
features/step_definitions/noosfero_steps.rb
@@ -692,11 +692,6 @@ Given /^the cache is turned (on|off)$/ do |state| @@ -692,11 +692,6 @@ Given /^the cache is turned (on|off)$/ do |state|
692 ActionController::Base.perform_caching = (state == 'on') 692 ActionController::Base.perform_caching = (state == 'on')
693 end 693 end
694 694
695 -When /^I make a AJAX request to (.*)$/ do |page|  
696 - header 'X-Requested-With', 'XMLHttpRequest'  
697 - visit(path_to(page))  
698 -end  
699 -  
700 Given /^the environment is configured to (.*) after login$/ do |option| 695 Given /^the environment is configured to (.*) after login$/ do |option|
701 redirection = case option 696 redirection = case option
702 when 'stay on the same page' 697 when 'stay on the same page'