Commit cc81e07501b41177911bd389ce1bba503e1bd206

Authored by Leandro Santos
2 parents 97e6b3c1 6e1949cf

merging with master

Showing 136 changed files with 2164 additions and 423 deletions   Show diff stats
@@ -92,6 +92,7 @@ Daniel Alves + Rafael Manzo <rr.manzo@gmail.com> @@ -92,6 +92,7 @@ Daniel Alves + Rafael Manzo <rr.manzo@gmail.com>
92 Daniela Soares Feitosa <danielafeitosa@colivre.coop.br> 92 Daniela Soares Feitosa <danielafeitosa@colivre.coop.br>
93 Daniel Bucher <daniel.bucher88@gmail.com> 93 Daniel Bucher <daniel.bucher88@gmail.com>
94 Daniel Cunha <daniel@colivre.coop.br> 94 Daniel Cunha <daniel@colivre.coop.br>
  95 +daniel <dtygel@eita.org.br>
95 David Carlos <ddavidcarlos1392@gmail.com> 96 David Carlos <ddavidcarlos1392@gmail.com>
96 diegoamc <diegoamc90@gmail.com> 97 diegoamc <diegoamc90@gmail.com>
97 Diego Araújo + Alessandro Palmeira <diegoamc90@gmail.com> 98 Diego Araújo + Alessandro Palmeira <diegoamc90@gmail.com>
@@ -120,6 +121,7 @@ Diego Araujo + Rodrigo Souto + Rafael Manzo &lt;rr.manzo@gmail.com&gt; @@ -120,6 +121,7 @@ Diego Araujo + Rodrigo Souto + Rafael Manzo &lt;rr.manzo@gmail.com&gt;
120 Diego + Jefferson <diegoamc90@gmail.com> 121 Diego + Jefferson <diegoamc90@gmail.com>
121 Diego Martinez <diegoamc90@gmail.com> 122 Diego Martinez <diegoamc90@gmail.com>
122 Diego + Renan <renanteruoc@gmail.com> 123 Diego + Renan <renanteruoc@gmail.com>
  124 +dtygel <dtygel@gmail.com>
123 DylanGuedes <djmgguedes@gmail.com> 125 DylanGuedes <djmgguedes@gmail.com>
124 Eduardo Passos <eduardo@risa.localdomain.localhost> 126 Eduardo Passos <eduardo@risa.localdomain.localhost>
125 Eduardo Passos <eduardosteps@gmail.com> 127 Eduardo Passos <eduardosteps@gmail.com>
@@ -144,6 +146,7 @@ Italo Valcy &lt;italo@dcc.ufba.br&gt; @@ -144,6 +146,7 @@ Italo Valcy &lt;italo@dcc.ufba.br&gt;
144 Jefferson Fernandes + Diego Araujo + Rafael Manzo <jeffs.fernandes@gmail.com> 146 Jefferson Fernandes + Diego Araujo + Rafael Manzo <jeffs.fernandes@gmail.com>
145 Jefferson Fernandes + Joao M. M. da Silva <jeffs.fernandes@gmail.com> 147 Jefferson Fernandes + Joao M. M. da Silva <jeffs.fernandes@gmail.com>
146 Jefferson Fernandes + Joao M. M. Silva <jeffs.fernandes@gmail.com> 148 Jefferson Fernandes + Joao M. M. Silva <jeffs.fernandes@gmail.com>
  149 +Jérôme Jutteau <j.jutteau@gmail.com>
147 João da Silva + Eduardo Morais + Rafael Manzo <rr.manzo@gmail.com> 150 João da Silva + Eduardo Morais + Rafael Manzo <rr.manzo@gmail.com>
148 João da Silva <jaodsilv@linux.ime.usp.br> 151 João da Silva <jaodsilv@linux.ime.usp.br>
149 João Marco Maciel da Silva + Rafael Manzo + Renan Teruo <jaodsilv@linux.ime.usp.br> 152 João Marco Maciel da Silva + Rafael Manzo + Renan Teruo <jaodsilv@linux.ime.usp.br>
@@ -247,8 +250,10 @@ Tallys Martins &lt;tallysmartins@gmail.com&gt; @@ -247,8 +250,10 @@ Tallys Martins &lt;tallysmartins@gmail.com&gt;
247 Tallys Martins <tallysmartins@yahoo.com.br> 250 Tallys Martins <tallysmartins@yahoo.com.br>
248 tallys <tallys@tallys> 251 tallys <tallys@tallys>
249 tallys <tallys@tallys.(none)> 252 tallys <tallys@tallys.(none)>
  253 +Thiago Casotti <thiago.casotti@uol.com.br>
250 Thiago Zoroastro <thiago.zoroastro@bol.com.br> 254 Thiago Zoroastro <thiago.zoroastro@bol.com.br>
251 Tuux <tuxa@galaxie.eu.org> 255 Tuux <tuxa@galaxie.eu.org>
  256 +TWS <tablettws@gmail.com>
252 Valessio Brito <contato@valessiobrito.com.br> 257 Valessio Brito <contato@valessiobrito.com.br>
253 Valessio Brito <contato@valessiobrito.info> 258 Valessio Brito <contato@valessiobrito.info>
254 Valessio Brito <valessio@gmail.com> 259 Valessio Brito <valessio@gmail.com>
@@ -20,18 +20,17 @@ gem &#39;locale&#39;, &#39;~&gt; 2.0.5&#39; @@ -20,18 +20,17 @@ gem &#39;locale&#39;, &#39;~&gt; 2.0.5&#39;
20 gem 'whenever', :require => false 20 gem 'whenever', :require => false
21 gem 'eita-jrails', '>= 0.9.5', :require => 'jrails' 21 gem 'eita-jrails', '>= 0.9.5', :require => 'jrails'
22 22
23 -group :assets do  
24 - gem 'uglifier', '>= 1.0.3'  
25 - gem 'sass-rails'  
26 -end 23 +# asset pipeline
  24 +gem 'uglifier', '>= 1.0.3'
  25 +gem 'sass-rails'
27 26
28 group :production do 27 group :production do
29 gem 'dalli', '~> 2.7.0' 28 gem 'dalli', '~> 2.7.0'
30 end 29 end
31 30
32 group :test do 31 group :test do
33 - gem 'rspec', '~> 2.10.0'  
34 - gem 'rspec-rails', '~> 2.10.1' 32 + gem 'rspec', '~> 2.14.0'
  33 + gem 'rspec-rails', '~> 2.14.1'
35 gem 'mocha', '~> 1.1.0', :require => false 34 gem 'mocha', '~> 1.1.0', :require => false
36 end 35 end
37 36
app/controllers/admin/role_controller.rb
@@ -2,7 +2,7 @@ class RoleController &lt; AdminController @@ -2,7 +2,7 @@ class RoleController &lt; AdminController
2 protect 'manage_environment_roles', :environment 2 protect 'manage_environment_roles', :environment
3 3
4 def index 4 def index
5 - @roles = environment.roles.find(:all) 5 + @roles = environment.roles.find(:all, :conditions => {:profile_id => nil})
6 end 6 end
7 7
8 def new 8 def new
app/controllers/application_controller.rb
@@ -9,6 +9,7 @@ class ApplicationController &lt; ActionController::Base @@ -9,6 +9,7 @@ class ApplicationController &lt; ActionController::Base
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 => [:private_environment?, :user] 11 before_filter :verify_members_whitelist, :if => [:private_environment?, :user]
  12 + before_filter :redirect_to_current_user
12 13
13 def verify_members_whitelist 14 def verify_members_whitelist
14 render_access_denied unless user.is_admin? || environment.in_whitelist?(user) 15 render_access_denied unless user.is_admin? || environment.in_whitelist?(user)
@@ -192,4 +193,15 @@ class ApplicationController &lt; ActionController::Base @@ -192,4 +193,15 @@ class ApplicationController &lt; ActionController::Base
192 def private_environment? 193 def private_environment?
193 @environment.enabled?(:restrict_to_members) 194 @environment.enabled?(:restrict_to_members)
194 end 195 end
  196 +
  197 + def redirect_to_current_user
  198 + if params[:profile] == '~'
  199 + if logged_in?
  200 + redirect_to params.merge(:profile => user.identifier)
  201 + else
  202 + render_not_found
  203 + end
  204 + end
  205 + end
  206 +
195 end 207 end
app/controllers/my_profile/cms_controller.rb
@@ -357,7 +357,8 @@ class CmsController &lt; MyProfileController @@ -357,7 +357,8 @@ class CmsController &lt; MyProfileController
357 @task.ip_address = request.remote_ip 357 @task.ip_address = request.remote_ip
358 @task.user_agent = request.user_agent 358 @task.user_agent = request.user_agent
359 @task.referrer = request.referrer 359 @task.referrer = request.referrer
360 - if verify_recaptcha(:model => @task, :message => _('Please type the words correctly')) && @task.save 360 + @task.requestor = current_person if logged_in?
  361 + if (logged_in? || verify_recaptcha(:model => @task, :message => _('Please type the words correctly'))) && @task.save
361 session[:notice] = _('Thanks for your suggestion. The community administrators were notified.') 362 session[:notice] = _('Thanks for your suggestion. The community administrators were notified.')
362 redirect_to @back_to 363 redirect_to @back_to
363 end 364 end
app/controllers/my_profile/profile_design_controller.rb
@@ -4,11 +4,19 @@ class ProfileDesignController &lt; BoxOrganizerController @@ -4,11 +4,19 @@ class ProfileDesignController &lt; BoxOrganizerController
4 4
5 protect 'edit_profile_design', :profile 5 protect 'edit_profile_design', :profile
6 6
7 - before_filter :protect_fixed_block, :only => [:save, :move_block] 7 + before_filter :protect_uneditable_block, :only => [:save]
  8 + before_filter :protect_fixed_block, :only => [:move_block]
  9 +
  10 + def protect_uneditable_block
  11 + block = boxes_holder.blocks.find(params[:id].gsub(/^block-/, ''))
  12 + if !current_person.is_admin? && !block.editable?
  13 + render_access_denied
  14 + end
  15 + end
8 16
9 def protect_fixed_block 17 def protect_fixed_block
10 block = boxes_holder.blocks.find(params[:id].gsub(/^block-/, '')) 18 block = boxes_holder.blocks.find(params[:id].gsub(/^block-/, ''))
11 - if block.fixed && !current_person.is_admin? 19 + if !current_person.is_admin? && !block.movable?
12 render_access_denied 20 render_access_denied
13 end 21 end
14 end 22 end
app/controllers/my_profile/profile_members_controller.rb
@@ -58,6 +58,7 @@ class ProfileMembersController &lt; MyProfileController @@ -58,6 +58,7 @@ class ProfileMembersController &lt; MyProfileController
58 58
59 def change_role 59 def change_role
60 @roles = Profile::Roles.organization_member_roles(environment.id) 60 @roles = Profile::Roles.organization_member_roles(environment.id)
  61 + @custom_roles = profile.custom_roles
61 begin 62 begin
62 @member = profile.members.find(params[:id]) 63 @member = profile.members.find(params[:id])
63 rescue ActiveRecord::RecordNotFound 64 rescue ActiveRecord::RecordNotFound
app/controllers/my_profile/profile_roles_controller.rb 0 → 100644
@@ -0,0 +1,116 @@ @@ -0,0 +1,116 @@
  1 +class ProfileRolesController < MyProfileController
  2 +
  3 + protect 'manage_custom_roles', :profile
  4 +
  5 + def index
  6 + @roles = profile.custom_roles
  7 + end
  8 +
  9 + def new
  10 + @role = Role.new
  11 + end
  12 +
  13 + def create
  14 + @role = Role.new({:name => params[:role][:name], :permissions => params[:role][:permissions], :environment => environment }, :without_protection => true)
  15 + if @role.save
  16 + profile.custom_roles << @role
  17 + redirect_to :action => 'show', :id => @role
  18 + else
  19 + session[:notice] = _('Failed to create role')
  20 + render :action => 'new'
  21 + end
  22 + end
  23 +
  24 + def show
  25 + @role = environment.roles.find(params[:id])
  26 + end
  27 +
  28 + def edit
  29 + @role = environment.roles.find(params[:id])
  30 + end
  31 +
  32 + def assign_role_by_members
  33 + return redirect_to "/" if params[:q].nil? or !request.xhr?
  34 + arg = params[:q].downcase
  35 + result = find_by_contents(:people, environment, profile.members, params[:q])[:results]
  36 + render :text => prepare_to_token_input(result).to_json
  37 + end
  38 +
  39 + def destroy
  40 + @role = environment.roles.find(params[:id])
  41 + @members = profile.members_by_role(@role)
  42 + @roles_list = all_roles(environment, profile)
  43 + @roles_list.delete(@role)
  44 + end
  45 +
  46 + def remove
  47 + @role = environment.roles.find(params[:id])
  48 + @members = profile.members_by_role(@role)
  49 + member_roles = params[:roles] ? environment.roles.find(params[:roles].select{|r|!r.to_i.zero?}) : []
  50 + append_roles(@members, member_roles, profile)
  51 + if @role.destroy
  52 + session[:notice] = _('Role successfuly removed!')
  53 + else
  54 + session[:notice] = _('Failed to remove role!')
  55 + end
  56 + redirect_to :action => 'index'
  57 + end
  58 +
  59 + def update
  60 + @role = environment.roles.find(params[:id])
  61 + if @role.update_attributes(params[:role])
  62 + redirect_to :action => 'show', :id => @role
  63 + else
  64 + session[:notice] = _('Failed to edit role')
  65 + render :action => 'edit'
  66 + end
  67 + end
  68 +
  69 + def assign
  70 + @role = environment.roles.find(params[:id])
  71 + @roles_list = all_roles(environment, profile)
  72 + @roles_list.delete(@role)
  73 + end
  74 +
  75 + def define
  76 + @role = environment.roles.find(params[:id])
  77 + selected_role = params[:selected_role] ? environment.roles.find(params[:selected_role].to_i) : nil
  78 + if params[:assign_role_by].eql? "members"
  79 + members_list = params[:person_id].split(',').collect {|id| environment.profiles.find(id.to_i)}
  80 + members_list.collect{|person| person.add_role(@role, profile)}
  81 + elsif params[:assign_role_by].eql? "roles"
  82 + members = profile.members_by_role(selected_role)
  83 + replace_role(members, selected_role, @role, profile)
  84 + else
  85 + session[:notice] = _("Error")
  86 + end
  87 + redirect_to :action => 'index'
  88 + end
  89 +
  90 + protected
  91 +
  92 + def append_roles(members, roles, profile)
  93 + members.each do |person|
  94 + all_roles = person.find_roles(profile).map(&:role) + roles
  95 + person.define_roles(all_roles, profile)
  96 + end
  97 + end
  98 +
  99 + def all_roles(environment, profile)
  100 + Profile::Roles.organization_member_roles(environment.id) + profile.custom_roles
  101 + end
  102 +
  103 + def replace_roles(members, roles, profile)
  104 + members.each do |person|
  105 + person.define_roles(roles, profile)
  106 + end
  107 + end
  108 +
  109 + def replace_role(members, role, new_role, profile)
  110 + members.each do |person|
  111 + person.remove_role(role, profile)
  112 + person.add_role(new_role, profile)
  113 + end
  114 + end
  115 +
  116 +end
app/helpers/application_helper.rb
@@ -707,6 +707,24 @@ module ApplicationHelper @@ -707,6 +707,24 @@ module ApplicationHelper
707 javascript_include_tag script if script 707 javascript_include_tag script if script
708 end 708 end
709 709
  710 + def template_path
  711 + if profile.nil?
  712 + "/designs/templates/#{environment.layout_template}"
  713 + else
  714 + "/designs/templates/#{profile.layout_template}"
  715 + end
  716 + end
  717 +
  718 + def template_javascript_src
  719 + script = File.join template_path, '/javascripts/template.js'
  720 + script if File.exists? File.join(Rails.root, 'public', script)
  721 + end
  722 +
  723 + def templete_javascript_ng
  724 + script = template_javascript_src
  725 + javascript_include_tag script if script
  726 + end
  727 +
710 def file_field_or_thumbnail(label, image, i) 728 def file_field_or_thumbnail(label, image, i)
711 display_form_field label, ( 729 display_form_field label, (
712 render :partial => (image && image.valid? ? 'shared/show_thumbnail' : 'shared/change_image'), 730 render :partial => (image && image.valid? ? 'shared/show_thumbnail' : 'shared/change_image'),
app/helpers/blog_helper.rb
@@ -17,28 +17,28 @@ module BlogHelper @@ -17,28 +17,28 @@ module BlogHelper
17 _('Configure blog') 17 _('Configure blog')
18 end 18 end
19 19
20 - def list_posts(articles, format = 'full', paginate = true) 20 + def list_posts(articles, conf = { format: 'full', paginate: true })
21 pagination = will_paginate(articles, { 21 pagination = will_paginate(articles, {
22 :param_name => 'npage', 22 :param_name => 'npage',
23 :previous_label => _('&laquo; Newer posts'), 23 :previous_label => _('&laquo; Newer posts'),
24 :next_label => _('Older posts &raquo;'), 24 :next_label => _('Older posts &raquo;'),
25 :params => {:action=>"view_page", :page=>articles.first.parent.path.split('/'), :controller=>"content_viewer"} 25 :params => {:action=>"view_page", :page=>articles.first.parent.path.split('/'), :controller=>"content_viewer"}
26 - }) if articles.present? && paginate 26 + }) if articles.present? && conf[:paginate]
27 content = [] 27 content = []
28 artic_len = articles.length 28 artic_len = articles.length
29 articles.each_with_index{ |art,i| 29 articles.each_with_index{ |art,i|
30 - css_add = [ 'position-'+(i+1).to_s() ] 30 + css_add = [ 'blog-post', 'position-'+(i+1).to_s() ]
31 position = (i%2 == 0) ? 'odd-post' : 'even-post' 31 position = (i%2 == 0) ? 'odd-post' : 'even-post'
32 css_add << 'first' if i == 0 32 css_add << 'first' if i == 0
33 css_add << 'last' if i == (artic_len-1) 33 css_add << 'last' if i == (artic_len-1)
34 css_add << 'not-published' if !art.published? 34 css_add << 'not-published' if !art.published?
35 - css_add << position + '-inner'  
36 - content << content_tag('div',  
37 - content_tag('div',  
38 - display_post(art, format).html_safe + '<br style="clear:both"/>'.html_safe,  
39 - :class => 'blog-post ' + css_add.join(' '),  
40 - :id => "post-#{art.id}"), :class => position  
41 - ) 35 + css_add << position
  36 + content << (content_tag 'div', id: "post-#{art.id}", class: css_add do
  37 + content_tag 'div', class: position + '-inner blog-post-inner' do
  38 + display_post(art, conf[:format]).html_safe +
  39 + '<br style="clear:both"/>'.html_safe
  40 + end
  41 + end)
42 } 42 }
43 content.join("\n<hr class='sep-posts'/>\n") + (pagination or '') 43 content.join("\n<hr class='sep-posts'/>\n") + (pagination or '')
44 end 44 end
@@ -46,7 +46,16 @@ module BlogHelper @@ -46,7 +46,16 @@ module BlogHelper
46 def display_post(article, format = 'full') 46 def display_post(article, format = 'full')
47 no_comments = (format == 'full') ? false : true 47 no_comments = (format == 'full') ? false : true
48 title = article_title(article, :no_comments => no_comments) 48 title = article_title(article, :no_comments => no_comments)
49 - html = send("display_#{format}_format", FilePresenter.for(article)).html_safe 49 + method = "display_#{format.split('+')[0]}_format"
  50 + html = send(method, FilePresenter.for(article)).html_safe
  51 + if format.split('+')[1] == 'pic'
  52 + img = article.first_image
  53 + if img.blank?
  54 + '<div class="post-pic empty"></div>'
  55 + else
  56 + '<div class="post-pic" style="background-image:url('+img+')"></div>'
  57 + end
  58 + end.to_s +
50 title + html 59 title + html
51 end 60 end
52 61
app/helpers/boxes_helper.rb
@@ -190,7 +190,7 @@ module BoxesHelper @@ -190,7 +190,7 @@ module BoxesHelper
190 else 190 else
191 "before-block-#{block.id}" 191 "before-block-#{block.id}"
192 end 192 end
193 - if block.nil? or modifiable?(block) 193 + if block.nil? || movable?(block)
194 content_tag('div', '&nbsp;', :id => id, :class => 'block-target' ) + drop_receiving_element(id, :url => { :action => 'move_block', :target => id }, :accept => box.acceptable_blocks, :hoverclass => 'block-target-hover') 194 content_tag('div', '&nbsp;', :id => id, :class => 'block-target' ) + drop_receiving_element(id, :url => { :action => 'move_block', :target => id }, :accept => box.acceptable_blocks, :hoverclass => 'block-target-hover')
195 else 195 else
196 "" 196 ""
@@ -199,14 +199,14 @@ module BoxesHelper @@ -199,14 +199,14 @@ module BoxesHelper
199 199
200 # makes the given block draggable so it can be moved away. 200 # makes the given block draggable so it can be moved away.
201 def block_handle(block) 201 def block_handle(block)
202 - modifiable?(block) ? draggable_element("block-#{block.id}", :revert => true) : "" 202 + movable?(block) ? draggable_element("block-#{block.id}", :revert => true) : ""
203 end 203 end
204 204
205 def block_edit_buttons(block) 205 def block_edit_buttons(block)
206 buttons = [] 206 buttons = []
207 nowhere = 'javascript: return false;' 207 nowhere = 'javascript: return false;'
208 208
209 - if modifiable?(block) 209 + if movable?(block)
210 if block.first? 210 if block.first?
211 buttons << icon_button('up-disabled', _("Can't move up anymore."), nowhere) 211 buttons << icon_button('up-disabled', _("Can't move up anymore."), nowhere)
212 else 212 else
@@ -229,15 +229,15 @@ module BoxesHelper @@ -229,15 +229,15 @@ module BoxesHelper
229 buttons << icon_button('left', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[1].id.to_s, :id => block.id }, :method => 'post' ) 229 buttons << icon_button('left', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[1].id.to_s, :id => block.id }, :method => 'post' )
230 end 230 end
231 end 231 end
  232 + end
232 233
233 - if block.editable?  
234 - buttons << modal_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id })  
235 - end 234 + if editable?(block)
  235 + buttons << modal_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id })
  236 + end
236 237
237 - if !block.main?  
238 - buttons << icon_button(:delete, _('Remove block'), { :action => 'remove', :id => block.id }, { :method => 'post', :confirm => _('Are you sure you want to remove this block?')})  
239 - buttons << icon_button(:clone, _('Clone'), { :action => 'clone_block', :id => block.id }, { :method => 'post' })  
240 - end 238 + if movable?(block) && !block.main?
  239 + buttons << icon_button(:delete, _('Remove block'), { :action => 'remove', :id => block.id }, { :method => 'post', :confirm => _('Are you sure you want to remove this block?')})
  240 + buttons << icon_button(:clone, _('Clone'), { :action => 'clone_block', :id => block.id }, { :method => 'post' })
241 end 241 end
242 242
243 if block.respond_to?(:help) 243 if block.respond_to?(:help)
@@ -273,7 +273,11 @@ module BoxesHelper @@ -273,7 +273,11 @@ module BoxesHelper
273 classes 273 classes
274 end 274 end
275 275
276 - def modifiable?(block)  
277 - return !block.fixed || environment.admins.include?(user) 276 + def movable?(block)
  277 + return block.movable? || user.is_admin?
  278 + end
  279 +
  280 + def editable?(block)
  281 + return block.editable? || user.is_admin?
278 end 282 end
279 end 283 end
app/helpers/layout_helper.rb
@@ -28,7 +28,7 @@ module LayoutHelper @@ -28,7 +28,7 @@ module LayoutHelper
28 end 28 end
29 29
30 def noosfero_javascript 30 def noosfero_javascript
31 - plugins_javascripts = @plugins.flat_map{ |plugin| plugin.js_files.map{ |js| plugin.class.public_path(js, true) } }.flatten 31 + plugins_javascripts = @plugins.flat_map{ |plugin| Array.wrap(plugin.js_files).map{ |js| plugin.class.public_path(js, true) } }.flatten
32 32
33 output = '' 33 output = ''
34 output += render 'layouts/javascript' 34 output += render 'layouts/javascript'
@@ -38,6 +38,8 @@ module LayoutHelper @@ -38,6 +38,8 @@ module LayoutHelper
38 output += theme_javascript_ng.to_s 38 output += theme_javascript_ng.to_s
39 output += javascript_tag 'render_all_jquery_ui_widgets()' 39 output += javascript_tag 'render_all_jquery_ui_widgets()'
40 40
  41 + output += templete_javascript_ng.to_s
  42 +
41 output 43 output
42 end 44 end
43 45
@@ -70,11 +72,7 @@ module LayoutHelper @@ -70,11 +72,7 @@ module LayoutHelper
70 end 72 end
71 73
72 def template_stylesheet_path 74 def template_stylesheet_path
73 - if profile.nil?  
74 - "/designs/templates/#{environment.layout_template}/stylesheets/style.css"  
75 - else  
76 - "/designs/templates/#{profile.layout_template}/stylesheets/style.css"  
77 - end 75 + File.join template_path, "/stylesheets/style.css"
78 end 76 end
79 77
80 78
app/helpers/tinymce_helper.rb
@@ -17,6 +17,7 @@ module TinymceHelper @@ -17,6 +17,7 @@ module TinymceHelper
17 searchreplace wordcount visualblocks visualchars code fullscreen 17 searchreplace wordcount visualblocks visualchars code fullscreen
18 insertdatetime media nonbreaking save table contextmenu directionality 18 insertdatetime media nonbreaking save table contextmenu directionality
19 emoticons template paste textcolor colorpicker textpattern], 19 emoticons template paste textcolor colorpicker textpattern],
  20 + :image_advtab => true,
20 :language => tinymce_language 21 :language => tinymce_language
21 22
22 options[:toolbar1] = "insertfile undo redo | copy paste | bold italic underline | styleselect fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image" 23 options[:toolbar1] = "insertfile undo redo | copy paste | bold italic underline | styleselect fontsizeselect | forecolor backcolor | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image"
app/models/article.rb
@@ -5,7 +5,7 @@ class Article &lt; ActiveRecord::Base @@ -5,7 +5,7 @@ class Article &lt; ActiveRecord::Base
5 :allow_members_to_edit, :translation_of_id, :language, 5 :allow_members_to_edit, :translation_of_id, :language,
6 :license_id, :parent_id, :display_posts_in_current_language, 6 :license_id, :parent_id, :display_posts_in_current_language,
7 :category_ids, :posts_per_page, :moderate_comments, 7 :category_ids, :posts_per_page, :moderate_comments,
8 - :accept_comments, :feed, :published, :source, 8 + :accept_comments, :feed, :published, :source, :source_name,
9 :highlighted, :notify_comments, :display_hits, :slug, 9 :highlighted, :notify_comments, :display_hits, :slug,
10 :external_feed_builder, :display_versions, :external_link, 10 :external_feed_builder, :display_versions, :external_link,
11 :image_builder, :show_to_followers 11 :image_builder, :show_to_followers
@@ -769,7 +769,9 @@ class Article &lt; ActiveRecord::Base @@ -769,7 +769,9 @@ class Article &lt; ActiveRecord::Base
769 end 769 end
770 770
771 def first_image 771 def first_image
772 - img = Nokogiri::HTML.fragment(self.lead.to_s).css('img[src]').first || Nokogiri::HTML.fragment(self.body.to_s).search('img').first 772 + img = ( image.present? && { 'src' => image.public_filename } ) ||
  773 + Nokogiri::HTML.fragment(self.lead.to_s).css('img[src]').first ||
  774 + Nokogiri::HTML.fragment(self.body.to_s).search('img').first
773 img.nil? ? '' : img['src'] 775 img.nil? ? '' : img['src']
774 end 776 end
775 777
app/models/block.rb
1 class Block < ActiveRecord::Base 1 class Block < ActiveRecord::Base
2 2
3 - attr_accessible :title, :display, :limit, :box_id, :posts_per_page, :visualization_format, :language, :display_user, :box, :fixed 3 + attr_accessible :title, :display, :limit, :box_id, :posts_per_page,
  4 + :visualization_format, :language, :display_user,
  5 + :box, :edit_modes, :move_modes
4 6
5 # to be able to generate HTML 7 # to be able to generate HTML
6 include ActionView::Helpers::UrlHelper 8 include ActionView::Helpers::UrlHelper
@@ -23,7 +25,7 @@ class Block &lt; ActiveRecord::Base @@ -23,7 +25,7 @@ class Block &lt; ActiveRecord::Base
23 end 25 end
24 26
25 def get_limit 27 def get_limit
26 - [0,limit].max 28 + [0,limit.to_i].max
27 end 29 end
28 30
29 def embed_code 31 def embed_code
@@ -110,8 +112,13 @@ class Block &lt; ActiveRecord::Base @@ -110,8 +112,13 @@ class Block &lt; ActiveRecord::Base
110 # * <tt>'all'</tt>: the block is always displayed 112 # * <tt>'all'</tt>: the block is always displayed
111 settings_items :language, :type => :string, :default => 'all' 113 settings_items :language, :type => :string, :default => 'all'
112 114
113 - # The block can be configured to be fixed. Only can be edited by environment admins  
114 - settings_items :fixed, :type => :boolean, :default => false 115 + # The block can be configured to define the edition modes options. Only can be edited by environment admins
  116 + # It can assume the following values:
  117 + #
  118 + # * <tt>'all'</tt>: the block owner has all edit options for this block
  119 + # * <tt>'none'</tt>: the block owner can't do anything with the block
  120 + settings_items :edit_modes, :type => :string, :default => 'all'
  121 + settings_items :move_modes, :type => :string, :default => 'all'
115 122
116 # returns the description of the block, used when the user sees a list of 123 # returns the description of the block, used when the user sees a list of
117 # blocks to choose one to include in the design. 124 # blocks to choose one to include in the design.
@@ -148,7 +155,11 @@ class Block &lt; ActiveRecord::Base @@ -148,7 +155,11 @@ class Block &lt; ActiveRecord::Base
148 155
149 # Is this block editable? (Default to <tt>false</tt>) 156 # Is this block editable? (Default to <tt>false</tt>)
150 def editable? 157 def editable?
151 - true 158 + self.edit_modes == "all"
  159 + end
  160 +
  161 + def movable?
  162 + self.move_modes == "all"
152 end 163 end
153 164
154 # must always return false, except on MainBlock clas. 165 # must always return false, except on MainBlock clas.
@@ -228,6 +239,21 @@ class Block &lt; ActiveRecord::Base @@ -228,6 +239,21 @@ class Block &lt; ActiveRecord::Base
228 } 239 }
229 end 240 end
230 241
  242 + def edit_block_options
  243 + @edit_options ||= {
  244 + 'all' => _('Can be modified'),
  245 + 'none' => _('Cannot be modified')
  246 + }
  247 + end
  248 +
  249 + def move_block_options
  250 + @move_options ||= {
  251 + 'all' => _('Can be moved'),
  252 + 'none' => _('Cannot be moved')
  253 + }
  254 + end
  255 +
  256 +
231 def duplicate 257 def duplicate
232 duplicated_block = self.dup 258 duplicated_block = self.dup
233 duplicated_block.display = 'never' 259 duplicated_block.display = 'never'
app/models/blog.rb
@@ -76,7 +76,7 @@ class Blog &lt; Folder @@ -76,7 +76,7 @@ class Blog &lt; Folder
76 end 76 end
77 77
78 settings_items :visualization_format, :type => :string, :default => 'full' 78 settings_items :visualization_format, :type => :string, :default => 'full'
79 - validates_inclusion_of :visualization_format, :in => [ 'full', 'short' ], :if => :visualization_format 79 + validates_inclusion_of :visualization_format, :in => [ 'full', 'short', 'short+pic' ], :if => :visualization_format
80 80
81 settings_items :display_posts_in_current_language, :type => :boolean, :default => false 81 settings_items :display_posts_in_current_language, :type => :boolean, :default => false
82 82
app/models/environment.rb
@@ -19,6 +19,8 @@ class Environment &lt; ActiveRecord::Base @@ -19,6 +19,8 @@ class Environment &lt; ActiveRecord::Base
19 filename 19 filename
20 end 20 end
21 21
  22 + NUMBER_OF_BOXES = 4
  23 +
22 PERMISSIONS['Environment'] = { 24 PERMISSIONS['Environment'] = {
23 'view_environment_admin_panel' => N_('View environment admin panel'), 25 'view_environment_admin_panel' => N_('View environment admin panel'),
24 'edit_environment_features' => N_('Edit environment features'), 26 'edit_environment_features' => N_('Edit environment features'),
@@ -172,7 +174,7 @@ class Environment &lt; ActiveRecord::Base @@ -172,7 +174,7 @@ class Environment &lt; ActiveRecord::Base
172 acts_as_having_boxes 174 acts_as_having_boxes
173 175
174 after_create do |env| 176 after_create do |env|
175 - 3.times do 177 + NUMBER_OF_BOXES.times do
176 env.boxes << Box.new 178 env.boxes << Box.new
177 end 179 end
178 180
@@ -737,8 +739,8 @@ class Environment &lt; ActiveRecord::Base @@ -737,8 +739,8 @@ class Environment &lt; ActiveRecord::Base
737 end 739 end
738 740
739 def is_default_template?(template) 741 def is_default_template?(template)
740 - is_default = template == community_default_template  
741 - is_default = is_default || template == person_default_template 742 + is_default = template == community_default_template
  743 + is_default = is_default || template == person_default_template
742 is_default = is_default || template == enterprise_default_template 744 is_default = is_default || template == enterprise_default_template
743 is_default 745 is_default
744 end 746 end
app/models/highlights_block.rb
@@ -26,8 +26,16 @@ class HighlightsBlock &lt; Block @@ -26,8 +26,16 @@ class HighlightsBlock &lt; Block
26 end 26 end
27 27
28 def featured_images 28 def featured_images
29 - block_images = images.select{|i| !i[:image_src].nil? }.sort { |x, y| x[:position] <=> y[:position] }  
30 - shuffle ? block_images.shuffle : block_images 29 + images = get_images
  30 + shuffle ? images.shuffle : images
  31 + end
  32 +
  33 + def get_images
  34 + images.select do |i|
  35 + !i[:image_src].nil?
  36 + end.sort do |x, y|
  37 + x[:position] <=> y[:position]
  38 + end
31 end 39 end
32 40
33 def content(args={}) 41 def content(args={})
app/models/organization.rb
@@ -29,6 +29,8 @@ class Organization &lt; Profile @@ -29,6 +29,8 @@ class Organization &lt; Profile
29 29
30 has_many :mailings, :class_name => 'OrganizationMailing', :foreign_key => :source_id, :as => 'source' 30 has_many :mailings, :class_name => 'OrganizationMailing', :foreign_key => :source_id, :as => 'source'
31 31
  32 + has_many :custom_roles, :class_name => 'Role', :foreign_key => :profile_id
  33 +
32 scope :more_popular, :order => 'members_count DESC' 34 scope :more_popular, :order => 'members_count DESC'
33 35
34 validate :presence_of_required_fieds, :unless => :is_template 36 validate :presence_of_required_fieds, :unless => :is_template
app/models/profile.rb
@@ -22,6 +22,8 @@ class Profile &lt; ActiveRecord::Base @@ -22,6 +22,8 @@ class Profile &lt; ActiveRecord::Base
22 :display => %w[compact] 22 :display => %w[compact]
23 } 23 }
24 24
  25 + NUMBER_OF_BOXES = 4
  26 +
25 def self.default_search_display 27 def self.default_search_display
26 'compact' 28 'compact'
27 end 29 end
@@ -43,7 +45,7 @@ class Profile &lt; ActiveRecord::Base @@ -43,7 +45,7 @@ class Profile &lt; ActiveRecord::Base
43 find_role('editor', env_id) 45 find_role('editor', env_id)
44 end 46 end
45 def self.organization_member_roles(env_id) 47 def self.organization_member_roles(env_id)
46 - all_roles(env_id).select{ |r| r.key.match(/^profile_/) unless r.key.blank? } 48 + all_roles(env_id).select{ |r| r.key.match(/^profile_/) unless r.key.blank? || !r.profile_id.nil?}
47 end 49 end
48 def self.all_roles(env_id) 50 def self.all_roles(env_id)
49 Role.all :conditions => { :environment_id => env_id } 51 Role.all :conditions => { :environment_id => env_id }
@@ -75,6 +77,7 @@ class Profile &lt; ActiveRecord::Base @@ -75,6 +77,7 @@ class Profile &lt; ActiveRecord::Base
75 'publish_content' => N_('Publish content'), 77 'publish_content' => N_('Publish content'),
76 'invite_members' => N_('Invite members'), 78 'invite_members' => N_('Invite members'),
77 'send_mail_to_members' => N_('Send e-Mail to members'), 79 'send_mail_to_members' => N_('Send e-Mail to members'),
  80 + 'manage_custom_roles' => N_('Manage custom roles'),
78 } 81 }
79 82
80 acts_as_accessible 83 acts_as_accessible
@@ -361,7 +364,7 @@ class Profile &lt; ActiveRecord::Base @@ -361,7 +364,7 @@ class Profile &lt; ActiveRecord::Base
361 if template 364 if template
362 apply_template(template, :copy_articles => false) 365 apply_template(template, :copy_articles => false)
363 else 366 else
364 - 3.times do 367 + NUMBER_OF_BOXES.times do
365 self.boxes << Box.new 368 self.boxes << Box.new
366 end 369 end
367 370
@@ -404,6 +407,7 @@ class Profile &lt; ActiveRecord::Base @@ -404,6 +407,7 @@ class Profile &lt; ActiveRecord::Base
404 alias_method_chain :template, :default 407 alias_method_chain :template, :default
405 408
406 def apply_template(template, options = {:copy_articles => true}) 409 def apply_template(template, options = {:copy_articles => true})
  410 + self.template = template
407 copy_blocks_from(template) 411 copy_blocks_from(template)
408 copy_articles_from(template) if options[:copy_articles] 412 copy_articles_from(template) if options[:copy_articles]
409 self.apply_type_specific_template(template) 413 self.apply_type_specific_template(template)
app/models/suggest_article.rb
1 class SuggestArticle < Task 1 class SuggestArticle < Task
2 2
3 - validates_presence_of :target_id, :article_name, :email, :name, :article_body 3 + validates_presence_of :target_id
  4 + validates_presence_of :email, :name, :if => Proc.new { |task| task.requestor.blank? }
  5 + validates_associated :article_object
4 6
5 settings_items :email, :type => String 7 settings_items :email, :type => String
6 settings_items :name, :type => String 8 settings_items :name, :type => String
7 - settings_items :article_name, :type => String  
8 - settings_items :article_body, :type => String  
9 - settings_items :article_abstract, :type => String  
10 - settings_items :article_parent_id, :type => String  
11 - settings_items :source, :type => String  
12 - settings_items :source_name, :type => String  
13 - settings_items :highlighted, :type => :boolean, :default => false  
14 settings_items :ip_address, :type => String 9 settings_items :ip_address, :type => String
15 settings_items :user_agent, :type => String 10 settings_items :user_agent, :type => String
16 settings_items :referrer, :type => String 11 settings_items :referrer, :type => String
  12 + settings_items :article, :type => Hash, :default => {}
17 13
18 after_create :schedule_spam_checking 14 after_create :schedule_spam_checking
19 15
@@ -24,34 +20,49 @@ class SuggestArticle &lt; Task @@ -24,34 +20,49 @@ class SuggestArticle &lt; Task
24 include Noosfero::Plugin::HotSpot 20 include Noosfero::Plugin::HotSpot
25 21
26 def sender 22 def sender
27 - "#{name} (#{email})" 23 + requestor ? "#{requestor.name}" : "#{name} (#{email})"
  24 + end
  25 +
  26 + def article_object
  27 + if @article_object.nil?
  28 + @article_object = article_type.new(article.merge({:profile => target}).except(:type))
  29 + if requestor.present?
  30 + @article_object.author = requestor
  31 + else
  32 + @article_object.author_name = name
  33 + end
  34 + end
  35 + @article_object
  36 + end
  37 +
  38 + def article_type
  39 + if article[:type].present?
  40 + type = article[:type].constantize
  41 + return type if type < Article
  42 + end
  43 + TinyMceArticle
28 end 44 end
29 45
30 def perform 46 def perform
31 - task = TinyMceArticle.new  
32 - task.profile = target  
33 - task.name = article_name  
34 - task.author_name = name  
35 - task.body = article_body  
36 - task.abstract = article_abstract  
37 - task.parent_id = article_parent_id  
38 - task.source = source  
39 - task.source_name = source_name  
40 - task.highlighted = highlighted  
41 - task.save! 47 + article_object.save!
42 end 48 end
43 49
44 def title 50 def title
45 _("Article suggestion") 51 _("Article suggestion")
46 end 52 end
47 53
  54 + def article_name
  55 + article[:name]
  56 + end
  57 +
48 def subject 58 def subject
49 article_name 59 article_name
50 end 60 end
51 61
52 def information 62 def information
53 - { :message => _('%{sender} suggested the publication of the article: %{subject}.'),  
54 - :variables => {:sender => sender} } 63 + variables = requestor.blank? ? {:requestor => sender} : {}
  64 + { :message => _('%{requestor} suggested the publication of the article: %{subject}.'),
  65 + :variables => variables }
55 end 66 end
56 67
57 def accept_details 68 def accept_details
@@ -63,8 +74,8 @@ class SuggestArticle &lt; Task @@ -63,8 +74,8 @@ class SuggestArticle &lt; Task
63 end 74 end
64 75
65 def target_notification_description 76 def target_notification_description
66 - _('%{sender} suggested the publication of the article: %{article}.') %  
67 - {:sender => sender, :article => article_name} 77 + _('%{requestor} suggested the publication of the article: %{article}.') %
  78 + {:requestor => sender, :article => article_name}
68 end 79 end
69 80
70 def target_notification_message 81 def target_notification_message
app/models/user.rb
@@ -45,7 +45,7 @@ class User &lt; ActiveRecord::Base @@ -45,7 +45,7 @@ class User &lt; ActiveRecord::Base
45 p = Person.new 45 p = Person.new
46 46
47 p.attributes = user.person_data 47 p.attributes = user.person_data
48 - p.identifier = user.login 48 + p.identifier = user.login if p.identifier.blank?
49 p.user = user 49 p.user = user
50 p.environment = user.environment 50 p.environment = user.environment
51 p.name ||= user.name || user.login 51 p.name ||= user.name || user.login
app/views/blocks/profile_info_actions/_join_leave_community.html.erb
1 -<div class='join-leave-button'> 1 +<div class='join-leave-button require-login-popup'>
2 <% if logged_in? %> 2 <% if logged_in? %>
3 <% if profile.members.include?(user) %> 3 <% if profile.members.include?(user) %>
4 <%= button(:delete, content_tag('span', _('Leave community')), profile.leave_url, 4 <%= button(:delete, content_tag('span', _('Leave community')), profile.leave_url,
app/views/box_organizer/edit.html.erb
@@ -5,12 +5,6 @@ @@ -5,12 +5,6 @@
5 5
6 <%= labelled_form_field(_('Custom title for this block: '), text_field(:block, :title, :maxlength => 20)) %> 6 <%= labelled_form_field(_('Custom title for this block: '), text_field(:block, :title, :maxlength => 20)) %>
7 7
8 - <% if environment.admins.include?(user) %>  
9 - <div class="fixed_block">  
10 - <%= labelled_check_box(_("Fixed"), "block[fixed]", value = "1", checked = @block.fixed) %>  
11 - </div>  
12 - <% end %>  
13 -  
14 <%= render :partial => partial_for_class(@block.class) %> 8 <%= render :partial => partial_for_class(@block.class) %>
15 9
16 <div class="display"> 10 <div class="display">
@@ -25,6 +19,15 @@ @@ -25,6 +19,15 @@
25 19
26 <%= labelled_form_field(_('Show for:'), select(:block, :language, [ [ _('all languages'), 'all']] + environment.locales.map {|key, value| [value, key]} )) %> 20 <%= labelled_form_field(_('Show for:'), select(:block, :language, [ [ _('all languages'), 'all']] + environment.locales.map {|key, value| [value, key]} )) %>
27 21
  22 + <% if user.is_admin? %>
  23 + <div class="edit-modes">
  24 + <%= labelled_form_field _('Edit options:'), select_tag('block[edit_modes]', options_from_collection_for_select(@block.edit_block_options, :first, :last, @block.edit_modes)) %>
  25 + </div>
  26 + <div class="move-modes">
  27 + <%= labelled_form_field _('Move options:'), select_tag('block[move_modes]', options_from_collection_for_select(@block.move_block_options, :first, :last, @block.move_modes)) %>
  28 + </div>
  29 + <% end %>
  30 +
28 <% button_bar do %> 31 <% button_bar do %>
29 <%= submit_button(:save, _('Save')) %> 32 <%= submit_button(:save, _('Save')) %>
30 <%= modal_close_button(_('Cancel')) %> 33 <%= modal_close_button(_('Cancel')) %>
app/views/cms/_blog.html.erb
@@ -64,7 +64,11 @@ @@ -64,7 +64,11 @@
64 <%= labelled_check_box(_('Remove cover image'),'remove_image',true,false)%> 64 <%= labelled_check_box(_('Remove cover image'),'remove_image',true,false)%>
65 <% end %> 65 <% end %>
66 66
67 -<%= labelled_form_field(_('How to display posts:'), f.select(:visualization_format, [ [ _('Full post'), 'full'], [ _('First paragraph'), 'short'] ])) %> 67 +<%= labelled_form_field(_('How to display posts:'), f.select(:visualization_format, [
  68 + [ _('Full post'), 'full'],
  69 + [ _('First paragraph'), 'short'],
  70 + [ _('First paragraph, with post picture'), 'short+pic']
  71 +])) %>
68 72
69 <%= labelled_form_field(_('Posts per page:'), f.select(:posts_per_page, Blog.posts_per_page_options)) %> 73 <%= labelled_form_field(_('Posts per page:'), f.select(:posts_per_page, Blog.posts_per_page_options)) %>
70 74
app/views/cms/suggest_an_article.html.erb
@@ -6,21 +6,22 @@ @@ -6,21 +6,22 @@
6 6
7 <%= labelled_form_for 'task' do |f| %> 7 <%= labelled_form_for 'task' do |f| %>
8 8
9 - <%= required labelled_form_field(_('Title'), text_field(:task, 'article_name', :size => 50)) %> 9 + <%= required labelled_form_field(_('Title'), text_field('task[article]', 'name', :size => 50)) %>
10 10
11 - <%= labelled_form_field(_('Source'), text_field(:task, 'source_name')) %> 11 + <%= labelled_form_field(_('Source'), text_field('task[article]', 'source_name')) %>
12 12
13 - <%= labelled_form_field(_('Source URL'), text_field(:task, 'source')) %> 13 + <%= labelled_form_field(_('Source URL'), text_field('task[article]', 'source')) %>
14 14
15 - <%= required labelled_form_field(_('Your name'), text_field(:task, 'name')) %>  
16 -  
17 - <%= required labelled_form_field(_('Email'), text_field(:task, 'email')) %> 15 + <% unless logged_in? %>
  16 + <%= required labelled_form_field(_('Your name'), text_field(:task, 'name')) %>
  17 + <%= required labelled_form_field(_('Email'), text_field(:task, 'email')) %>
  18 + <% end %>
18 19
19 - <%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true, :object => :task, :abstract_method => 'article_abstract', :body_method => 'article_body'} %> 20 + <%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true, :object => 'task[article]'} %>
20 21
21 <%= hidden_field_tag('back_to', @back_to) %> 22 <%= hidden_field_tag('back_to', @back_to) %>
22 23
23 - <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) %> 24 + <%= recaptcha_tags(:display => { :theme => 'clean' }, :ajax => true) unless logged_in? %>
24 25
25 <% button_bar do %> 26 <% button_bar do %>
26 <%= submit_button :save, _('Save') %> 27 <%= submit_button :save, _('Save') %>
app/views/content_viewer/blog_page.html.erb
@@ -18,6 +18,9 @@ @@ -18,6 +18,9 @@
18 format = inside_block.visualization_format 18 format = inside_block.visualization_format
19 paginate = false 19 paginate = false
20 end 20 end
21 - (blog.empty? ? content_tag('em', _('(no posts)')) : list_posts(posts, format, paginate)) 21 + (blog.empty? ?
  22 + content_tag('em', _('(no posts)')) :
  23 + list_posts(posts, format: format, paginate: paginate)
  24 + )
22 %> 25 %>
23 </div> 26 </div>
app/views/features/manage_fields.html.erb
1 <h1><%= _('Manage fields displayed for profiles') %></h1> 1 <h1><%= _('Manage fields displayed for profiles') %></h1>
2 2
  3 +<%= javascript_include_tag "manage-fields.js" %>
  4 +
3 <% tabs = [] %> 5 <% tabs = [] %>
4 <% tabs << {:title => _("Person's fields"), :id => 'person-fields', 6 <% tabs << {:title => _("Person's fields"), :id => 'person-fields',
5 :content => (render :partial => 'manage_person_fields')} %> 7 :content => (render :partial => 'manage_person_fields')} %>
@@ -11,5 +13,3 @@ @@ -11,5 +13,3 @@
11 <% end %> 13 <% end %>
12 14
13 <%= render_tabs(tabs) %> 15 <%= render_tabs(tabs) %>
14 -  
15 -<%= javascript_include_tag "manage-fields.js" %>  
app/views/profile/report_abuse.html.erb
@@ -24,7 +24,7 @@ @@ -24,7 +24,7 @@
24 $('#report-abuse-submit-button').css('cursor', 'progress'); 24 $('#report-abuse-submit-button').css('cursor', 'progress');
25 $.ajax({ 25 $.ajax({
26 type: 'POST', 26 type: 'POST',
27 - url: <%= url_for({:controller => 'profile', :action => 'register_report', :profile => profile.identifier}) %>, 27 + url: <%= url_for({:controller => 'profile', :action => 'register_report', :profile => profile.identifier}).to_json %>,
28 data: $(form).serialize(), 28 data: $(form).serialize(),
29 dataType: 'json', 29 dataType: 'json',
30 success: function(data, status, ajax){ 30 success: function(data, status, ajax){
app/views/profile_editor/edit.html.erb
1 <h1><%= _('Profile settings for %s') % profile.name %></h1> 1 <h1><%= _('Profile settings for %s') % profile.name %></h1>
2 2
3 -<%= javascript_include_tag 'deactivate_profile' %>  
4 <%= error_messages_for :profile_data %> 3 <%= error_messages_for :profile_data %>
5 4
6 <%= labelled_form_for :profile_data, :html => { :id => 'profile-data', :multipart => true } do |f| %> 5 <%= labelled_form_for :profile_data, :html => { :id => 'profile-data', :multipart => true } do |f| %>
app/views/profile_editor/index.html.erb
@@ -28,6 +28,8 @@ @@ -28,6 +28,8 @@
28 28
29 <%= control_panel_button(_('Manage Content'), 'cms', :controller => 'cms') %> 29 <%= control_panel_button(_('Manage Content'), 'cms', :controller => 'cms') %>
30 30
  31 + <%= control_panel_button(_('Manage Roles'), 'roles', :controller => 'profile_roles') %>
  32 +
31 <% unless profile.enterprise? %> 33 <% unless profile.enterprise? %>
32 <%= case profile.blogs.count 34 <%= case profile.blogs.count
33 when 0 35 when 0
app/views/profile_members/change_role.html.erb
1 <h3> <%= _('Changing role of %s') % @member.name %> </h3> 1 <h3> <%= _('Changing role of %s') % @member.name %> </h3>
2 2
3 <%= labelled_form_for :member, :url => {:action => 'update_roles'} do |f| %> 3 <%= labelled_form_for :member, :url => {:action => 'update_roles'} do |f| %>
4 -  
5 - <%= _('Roles:') %> <br> 4 +
  5 + <h4><%= _('Roles:') %></h4>
6 <% @roles.each do |r| %> 6 <% @roles.each do |r| %>
7 <%= labelled_check_box(r.name, 'roles[]', r.id, @associations.map(&:role).include?(r) ) %><br/> 7 <%= labelled_check_box(r.name, 'roles[]', r.id, @associations.map(&:role).include?(r) ) %><br/>
8 <ul class="role-permissions"> 8 <ul class="role-permissions">
@@ -11,6 +11,17 @@ @@ -11,6 +11,17 @@
11 <% end %> 11 <% end %>
12 </ul> 12 </ul>
13 <% end %> 13 <% end %>
  14 + <% unless @custom_roles.empty? %>
  15 + <h4><%= _('Custom Roles:') %></h4>
  16 + <% @custom_roles.each do |r| %>
  17 + <%= labelled_check_box(r.name, 'roles[]', r.id, @associations.map(&:role).include?(r) ) %><br/>
  18 + <ul class="role-permissions">
  19 + <% r.permissions.each do |p| %>
  20 + <li> <%= permission_name(p) %> </li>
  21 + <% end %>
  22 + </ul>
  23 + <% end %>
  24 + <% end %>
14 <%= hidden_field_tag 'person', @member.id %> 25 <%= hidden_field_tag 'person', @member.id %>
15 26
16 <% button_bar do %> 27 <% button_bar do %>
app/views/profile_roles/_form.html.erb 0 → 100644
@@ -0,0 +1,22 @@ @@ -0,0 +1,22 @@
  1 +<%= error_messages_for :role %>
  2 +
  3 +<%= labelled_form_for :role, :url => (mode == :edit) ? {:action => 'update', :id => role} : {:action => 'create'} do |f| %>
  4 +
  5 + <%= required_fields_message %>
  6 +
  7 + <%= required f.text_field(:name) %>
  8 +
  9 + <% permissions.each do |key| %>
  10 + <div class="permissions <%= key.downcase %>">
  11 + <h4><%= _('%s Permissions:' % key) %></h4>
  12 + <% ActiveRecord::Base::PERMISSIONS[key].keys.each do |p| %>
  13 + <%= check_box_tag("role[permissions][]", p, role.has_permission?(p), { :id => p }) %>
  14 + <%= content_tag(:label, permission_name(p), { :for => p }) %><br/>
  15 + <% end %>
  16 + </div>
  17 + <% end %>
  18 +
  19 + <% button_bar do %>
  20 + <%= submit_button('save', (mode == :edit) ? _('Save changes') : _('Create role'), :cancel => {:action => 'index'} ) %>
  21 + <% end %>
  22 +<% end %>
app/views/profile_roles/assign.html.erb 0 → 100644
@@ -0,0 +1,35 @@ @@ -0,0 +1,35 @@
  1 +<%= javascript_include_tag('assign_role.js') %>
  2 +
  3 +<h1> <%= _("Assign #{@role.name}") %> </h1>
  4 +
  5 +
  6 +<%= labelled_form_for :role, :url => { :action => 'define', :id => @role.id } do |f| %>
  7 +
  8 + <h2>
  9 + <%= _("Assign role by:") %>
  10 + </h2>
  11 + <p>
  12 + <%= labelled_radio_button _("Members"), :assign_role_by, "members", true, :id => "assign_role_by_members", :class => "assign_role_by" %>
  13 + &nbsp;
  14 + <%= labelled_radio_button _("Roles"), :assign_role_by, "roles", false, :id => "assign_role_by_roles", :class => "assign_role_by" %>
  15 + </p>
  16 + <div class="assign_by_members">
  17 + <%=token_input_field_tag(:person_id, 'search-profile-members', {:action => 'assign_role_by_members'},
  18 + {:focus => false, :hint_text => _('Select members to assign the role')}) %>
  19 +
  20 + <% button_bar do %>
  21 + <%= submit_button(:forward, _("Confirm")) %>
  22 + <% end %>
  23 + </div>
  24 + <div class="assign_by_roles" style="display: none;">
  25 + <h6>
  26 + <%= _("Replace role: ") %>
  27 + </h6>
  28 + <% @roles_list.each do |role| %>
  29 + <%= labelled_radio_button role.name , :selected_role, role.id , false, :class => "selected_role" %> <br>
  30 + <% end %>
  31 + <% button_bar do %>
  32 + <%= submit_button('save',_('Confirm'), :cancel => {:action => 'index'} ) %>
  33 + <% end %>
  34 + </div>
  35 +<% end %>
app/views/profile_roles/destroy.html.erb 0 → 100644
@@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
  1 +<h1> <%= _("Deleting #{@role.name}") %> </h1>
  2 +
  3 +<% if @members.nil? || @members.empty? %>
  4 + <p><%= _('This role is not being currently used.')%></p>
  5 + <p><%= _('Are you sure you want to delete this role?') %></p>
  6 +
  7 + <% button_bar do %>
  8 + <%= button(:remove, _('Yes, I am sure'), {:action => 'remove', :id => @role.id}, :method => :post) %>
  9 + <%= button(:cancel, _('No, I gave up'), {:action => 'index'}) %>
  10 + <% end %>
  11 +<% else %>
  12 + <p><%= _('There are members currently using this role.')%></p>
  13 + <p><%= _('To which role do you want to change them?') %></p>
  14 + <%= labelled_form_for :role, :url => { :action => 'remove', :id => @role.id } do |f| %>
  15 + <% @roles_list.each do |role| %>
  16 + <%= check_box_tag("roles[]", role.id, false ,{:id => role.key}) %>
  17 + <%= content_tag(:label, role.name, { :for => role.key }) %><br/>
  18 + <% end %>
  19 + <% button_bar do %>
  20 + <%= submit_button('save',_('Delete role'), :cancel => {:action => 'index'} ) %>
  21 + <% end %>
  22 + <% end %>
  23 +<% end %>
app/views/profile_roles/edit.html.erb 0 → 100644
@@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
  1 +<h1> <%= _("Editing #{@role.name}") %> </h1>
  2 +
  3 +<%= render :partial => 'form', :locals => { :mode => :edit, :role => @role, :permissions => [@role.kind] } %>
app/views/profile_roles/index.html.erb 0 → 100644
@@ -0,0 +1,27 @@ @@ -0,0 +1,27 @@
  1 +<h1><%= _('Manage user roles') %></h1>
  2 +
  3 +<table>
  4 + <tr>
  5 + <th><%= _('Role') %></th>
  6 + <th><%= _('Actions') %></th>
  7 + </tr>
  8 + <% @roles.each do |role| %>
  9 + <tr>
  10 + <td>
  11 + <%= link_to role.name, :action => 'show', :id => role %>
  12 + </td>
  13 + <td>
  14 + <div style="text-align: center;">
  15 + <%= button_without_text :edit, _('Edit'), :action => 'edit', :id => role %>
  16 + <%= button_without_text :delete, _('Delete'), :action => 'destroy', :id => role %>
  17 + <%= button_without_text 'vertical-toggle', _('Assign'), :action => 'assign', :id => role %>
  18 + </div>
  19 + </td>
  20 + </tr>
  21 + <% end %>
  22 +</table>
  23 +
  24 +<% button_bar do %>
  25 + <%= button :add, _('Create a new role'), :action => 'new' %>
  26 + <%= button :back, _('Back to control panel'), :controller => 'profile_editor' %>
  27 +<% end %>
app/views/profile_roles/new.html.erb 0 → 100644
@@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
  1 +<h1> <%= _("Create a new role") %> </h1>
  2 +
  3 +<%= render :partial => 'form', :locals => { :mode => :create, :role => @role, :permissions => ['Profile'] } %>
app/views/profile_roles/show.html.erb 0 → 100644
@@ -0,0 +1,13 @@ @@ -0,0 +1,13 @@
  1 +<h1> <%= _(@role.name) %></h1>
  2 +
  3 +<h3> <%= _('Permissions') %> </h3>
  4 +<ul>
  5 + <% @role.permissions.each do |p| %>
  6 + <li> <%= permission_name(p) %> </li>
  7 + <% end %>
  8 +</ul>
  9 +
  10 +<% button_bar do %>
  11 + <%= button :edit, _('Edit'), :action => 'edit', :id => @role %>
  12 + <%= button :back, _('Back to roles management'), :action => 'index' %>
  13 +<% end %>
app/views/shared/_profile_search_form.html.erb
  1 +<% search_label = _("Find in %s's content") % profile.short_name %>
1 <%= form_tag( { :controller => 'profile_search', :profile => profile.identifier}, :method => 'get', :class => 'search_form' ) do %> 2 <%= form_tag( { :controller => 'profile_search', :profile => profile.identifier}, :method => 'get', :class => 'search_form' ) do %>
2 <div class="search-field"> 3 <div class="search-field">
3 <span class="formfield"> 4 <span class="formfield">
4 - <%= search_input_with_suggestions 'q', :articles, @q, :title => _("Find in %s's content") % profile.short_name %> 5 + <%= search_input_with_suggestions 'q', :articles, @q, :title => search_label, :placeholder => search_label %>
5 </span> 6 </span>
6 <%= submit_button(:search, _('Search')) %> 7 <%= submit_button(:search, _('Search')) %>
7 <div> 8 <div>
app/views/spam/_suggest_article.html.erb
@@ -7,13 +7,13 @@ @@ -7,13 +7,13 @@
7 <ul class="suggest-article-details" style="display: none"> 7 <ul class="suggest-article-details" style="display: none">
8 <li><strong><%=_('Sent by')%></strong>: <%=task.name%> </li> 8 <li><strong><%=_('Sent by')%></strong>: <%=task.name%> </li>
9 <li><strong><%=_('Email')%></strong>: <%=task.email%> </li> 9 <li><strong><%=_('Email')%></strong>: <%=task.email%> </li>
10 - <li><strong><%=_('Source')%></strong>: <%=task.source_name%> </li>  
11 - <li><strong><%=_('Source URL')%></strong>: <%=task.source%> </li>  
12 - <li><strong><%=_('Folder')%></strong>: <%=(a = Article.find_by_id(task.article_parent_id))?a.name : '<em>' + s_('Folder|none') + '</em>'%> </li>  
13 - <li><strong><%=_('Lead')%></strong>: <%=task.article_abstract.blank? ? '<em>' + s_('Abstract|empty') + '</em>' : task.article_abstract%> </li> 10 + <li><strong><%=_('Source')%></strong>: <%=task.article_object.source_name%> </li>
  11 + <li><strong><%=_('Source URL')%></strong>: <%=task.article_object.source%> </li>
  12 + <li><strong><%=_('Folder')%></strong>: <%=(a = Article.find_by_id(task.article_object.parent_id))?a.name : '<em>' + s_('Folder|none') + '</em>'%> </li>
  13 + <li><strong><%=_('Lead')%></strong>: <%=task.article_object.abstract.blank? ? '<em>' + s_('Abstract|empty') + '</em>' : task.article_object.abstract%> </li>
14 <li><strong><%=_('Body')%></strong>: 14 <li><strong><%=_('Body')%></strong>:
15 <div class='suggest-article-body'> 15 <div class='suggest-article-body'>
16 - <%= task.article_body %> 16 + <%= task.article_object.body %>
17 </div> 17 </div>
18 </li> 18 </li>
19 </ul> 19 </ul>
app/views/tasks/_add_member_accept_details.html.erb
1 <%= content = _("Roles:")+"<br />" 1 <%= content = _("Roles:")+"<br />"
2 -roles = Profile::Roles.organization_member_roles(task.target.environment.id) 2 +roles = Profile::Roles.organization_member_roles(task.target.environment.id) + profile.custom_roles
3 roles.each do |role| 3 roles.each do |role|
4 content += labelled_check_box(role.name, "tasks[#{task.id}][task][roles][]", role.id, false)+"<br />" 4 content += labelled_check_box(role.name, "tasks[#{task.id}][task][roles][]", role.id, false)+"<br />"
5 end 5 end
6 content_tag('p', content, :class => 'member-classify-suggestion') 6 content_tag('p', content, :class => 'member-classify-suggestion')
7 %> 7 %>
8 -  
app/views/tasks/_suggest_article_accept_details.html.erb
1 <%= render :file => 'shared/tiny_mce' %> 1 <%= render :file => 'shared/tiny_mce' %>
2 2
3 -<%= labelled_form_field(_("Sent by: "), f.text_field(:name)) %>  
4 -<p><%= label_tag(_("Email: %s") % task.email) %> </p>  
5 -<%= required labelled_form_field(_('Title'), f.text_field(:article_name, :size => 50)) %>  
6 -<%= labelled_form_field(_('Source'), f.text_field(:source_name)) %>  
7 -<%= labelled_form_field(_("Source URL"), f.text_field(:source)) %> 3 +<% unless task.requestor %>
  4 + <%= labelled_form_field(_("Sent by: "), f.text_field(:name)) %>
  5 + <p><%= label_tag(_("Email: %s") % task.email) %> </p>
  6 +<% end %>
8 7
9 -<%= select_profile_folder(_('Select the folder where the article must be published'), "tasks[#{task.id}][task][article_parent_id]", task.target) %>  
10 -<%= labelled_form_field(_('Highlight this article'), f.check_box(:highlighted)) %> 8 +<%= f.fields_for 'article', OpenStruct.new(task.article) do |a| %>
  9 + <%= required labelled_form_field(_('Title'), a.text_field(:name, :size => 50)) %>
  10 + <%= labelled_form_field(_('Source'), a.text_field(:source_name)) %>
  11 + <%= labelled_form_field(_("Source URL"), a.text_field(:source)) %>
11 12
12 -<%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true, :f => f, :abstract_method => 'article_abstract', :body_method => 'article_body', :lead_id => task.id} %> 13 + <%= select_profile_folder(_('Select the folder where the article must be published'), "tasks[#{task.id}][task][article][parent_id]", task.target, task.article[:parent_id]) %>
  14 + <%= labelled_form_field(_('Highlight this article'), a.check_box(:highlighted)) %>
  15 +
  16 + <%= a.hidden_field(:type) %>
  17 +
  18 + <%= render :partial => 'shared/lead_and_body', :locals => {:tiny_mce => true, :f => a, :lead_id => task.id} %>
  19 +<% end %>
app/views/user_mailer/profiles_suggestions_email.html.erb
@@ -10,8 +10,8 @@ @@ -10,8 +10,8 @@
10 <% @people_suggestions.each do |person| %> 10 <% @people_suggestions.each do |person| %>
11 <li><a href="<%= url_for(person.public_profile_url) %>"><%= person.name %></a></li> 11 <li><a href="<%= url_for(person.public_profile_url) %>"><%= person.name %></a></li>
12 <% end %> 12 <% end %>
13 - <ul>  
14 - <%= _("To see the full list of friends suggestions, follow the link: %s") % @people_suggestions_url %> 13 + </ul>
  14 + <%= _("To see the full list of friends suggestions, follow the link: %s") % url_for(@people_suggestions_url) %>
15 <% end %> 15 <% end %>
16 16
17 <% unless @communities_suggestions.empty? %> 17 <% unless @communities_suggestions.empty? %>
@@ -21,13 +21,15 @@ @@ -21,13 +21,15 @@
21 <% @communities_suggestions.each do |community| %> 21 <% @communities_suggestions.each do |community| %>
22 <li><a href="<%= url_for(community.public_profile_url) %>"><%= community.name %></a></li> 22 <li><a href="<%= url_for(community.public_profile_url) %>"><%= community.name %></a></li>
23 <% end %> 23 <% end %>
24 - <ul>  
25 - <%= _("To see the full list of communities suggestions, follow the link: %s") % @communities_suggestions_url %> 24 + </ul>
  25 + <%= _("To see the full list of communities suggestions, follow the link: %s") % url_for(@communities_suggestions_url) %>
26 <% end %> 26 <% end %>
27 27
28 28
29 <%= _("Greetings,") %> 29 <%= _("Greetings,") %>
30 30
31 ---  
32 -<%= _('%s team.') % @environment %> 31 +<p><%= _("Greetings,") %></p>
  32 +
  33 +--<br/>
  34 +<%= _('%s team.') % @environment %><br/>
33 <%= @url %> 35 <%= @url %>
config/environments/development.rb
@@ -35,4 +35,8 @@ Noosfero::Application.configure do @@ -35,4 +35,8 @@ Noosfero::Application.configure do
35 config.assets.debug = true 35 config.assets.debug = true
36 36
37 config.consider_all_requests_local = true 37 config.consider_all_requests_local = true
  38 +
  39 + # send emails to /tmp/mails
  40 + config.action_mailer.delivery_method = :file
  41 +
38 end 42 end
config/routes.rb
@@ -56,37 +56,37 @@ Noosfero::Application.routes.draw do @@ -56,37 +56,37 @@ Noosfero::Application.routes.draw do
56 match 'search(/:action(/*category_path))', :controller => 'search' 56 match 'search(/:action(/*category_path))', :controller => 'search'
57 57
58 # events 58 # events
59 - match 'profile/:profile/events_by_day', :controller => 'events', :action => 'events_by_day', :profile => /#{Noosfero.identifier_format}/  
60 - match 'profile/:profile/events_by_month', :controller => 'events', :action => 'events_by_month', :profile => /#{Noosfero.identifier_format}/  
61 - match 'profile/:profile/events/:year/:month/:day', :controller => 'events', :action => 'events', :year => /\d*/, :month => /\d*/, :day => /\d*/, :profile => /#{Noosfero.identifier_format}/  
62 - match 'profile/:profile/events/:year/:month', :controller => 'events', :action => 'events', :year => /\d*/, :month => /\d*/, :profile => /#{Noosfero.identifier_format}/  
63 - match 'profile/:profile/events', :controller => 'events', :action => 'events', :profile => /#{Noosfero.identifier_format}/ 59 + match 'profile/:profile/events_by_day', :controller => 'events', :action => 'events_by_day', :profile => /#{Noosfero.identifier_format_in_url}/
  60 + match 'profile/:profile/events_by_month', :controller => 'events', :action => 'events_by_month', :profile => /#{Noosfero.identifier_format_in_url}/
  61 + match 'profile/:profile/events/:year/:month/:day', :controller => 'events', :action => 'events', :year => /\d*/, :month => /\d*/, :day => /\d*/, :profile => /#{Noosfero.identifier_format_in_url}/
  62 + match 'profile/:profile/events/:year/:month', :controller => 'events', :action => 'events', :year => /\d*/, :month => /\d*/, :profile => /#{Noosfero.identifier_format_in_url}/
  63 + match 'profile/:profile/events', :controller => 'events', :action => 'events', :profile => /#{Noosfero.identifier_format_in_url}/
64 64
65 # catalog 65 # catalog
66 - match 'catalog/:profile', :controller => 'catalog', :action => 'index', :profile => /#{Noosfero.identifier_format}/, :as => :catalog 66 + match 'catalog/:profile', :controller => 'catalog', :action => 'index', :profile => /#{Noosfero.identifier_format_in_url}/, :as => :catalog
67 67
68 # invite 68 # invite
69 - match 'profile/:profile/invite/friends', :controller => 'invite', :action => 'invite_friends', :profile => /#{Noosfero.identifier_format}/  
70 - match 'profile/:profile/invite/:action', :controller => 'invite', :profile => /#{Noosfero.identifier_format}/ 69 + match 'profile/:profile/invite/friends', :controller => 'invite', :action => 'invite_friends', :profile => /#{Noosfero.identifier_format_in_url}/
  70 + match 'profile/:profile/invite/:action', :controller => 'invite', :profile => /#{Noosfero.identifier_format_in_url}/
71 71
72 # feeds per tag 72 # feeds per tag
73 - match 'profile/:profile/tags/:id/feed', :controller => 'profile', :action =>'tag_feed', :id => /.+/, :profile => /#{Noosfero.identifier_format}/, :as => :tag_feed 73 + match 'profile/:profile/tags/:id/feed', :controller => 'profile', :action =>'tag_feed', :id => /.+/, :profile => /#{Noosfero.identifier_format_in_url}/, :as => :tag_feed
74 74
75 # profile tags 75 # profile tags
76 - match 'profile/:profile/tags/:id', :controller => 'profile', :action => 'content_tagged', :id => /.+/, :profile => /#{Noosfero.identifier_format}/  
77 - match 'profile/:profile/tags(/:id)', :controller => 'profile', :action => 'tags', :profile => /#{Noosfero.identifier_format}/ 76 + match 'profile/:profile/tags/:id', :controller => 'profile', :action => 'content_tagged', :id => /.+/, :profile => /#{Noosfero.identifier_format_in_url}/
  77 + match 'profile/:profile/tags(/:id)', :controller => 'profile', :action => 'tags', :profile => /#{Noosfero.identifier_format_in_url}/
78 78
79 # profile search 79 # profile search
80 - match 'profile/:profile/search', :controller => 'profile_search', :action => 'index', :profile => /#{Noosfero.identifier_format}/ 80 + match 'profile/:profile/search', :controller => 'profile_search', :action => 'index', :profile => /#{Noosfero.identifier_format_in_url}/
81 81
82 # comments 82 # comments
83 - match 'profile/:profile/comment/:action/:id', :controller => 'comment', :profile => /#{Noosfero.identifier_format}/ 83 + match 'profile/:profile/comment/:action/:id', :controller => 'comment', :profile => /#{Noosfero.identifier_format_in_url}/
84 84
85 # public profile information 85 # public profile information
86 - match 'profile/:profile(/:action(/:id))', :controller => 'profile', :action => 'index', :id => /[^\/]*/, :profile => /#{Noosfero.identifier_format}/, :as => :profile 86 + match 'profile/:profile(/:action(/:id))', :controller => 'profile', :action => 'index', :id => /[^\/]*/, :profile => /#{Noosfero.identifier_format_in_url}/, :as => :profile
87 87
88 # contact 88 # contact
89 - match 'contact/:profile/:action(/:id)', :controller => 'contact', :action => 'index', :id => /.*/, :profile => /#{Noosfero.identifier_format}/ 89 + match 'contact/:profile/:action(/:id)', :controller => 'contact', :action => 'index', :id => /.*/, :profile => /#{Noosfero.identifier_format_in_url}/
90 90
91 # map balloon 91 # map balloon
92 match 'map_balloon/:action/:id', :controller => 'map_balloon', :id => /.*/ 92 match 'map_balloon/:action/:id', :controller => 'map_balloon', :id => /.*/
@@ -98,8 +98,8 @@ Noosfero::Application.routes.draw do @@ -98,8 +98,8 @@ Noosfero::Application.routes.draw do
98 ## Controllers that are profile-specific (for profile admins ) 98 ## Controllers that are profile-specific (for profile admins )
99 ###################################################### 99 ######################################################
100 # profile customization - "My profile" 100 # profile customization - "My profile"
101 - match 'myprofile/:profile', :controller => 'profile_editor', :action => 'index', :profile => /#{Noosfero.identifier_format}/  
102 - match 'myprofile/:profile/:controller(/:action(/:id))', :controller => Noosfero.pattern_for_controllers_in_directory('my_profile'), :profile => /#{Noosfero.identifier_format}/, :as => :myprofile 101 + match 'myprofile/:profile', :controller => 'profile_editor', :action => 'index', :profile => /#{Noosfero.identifier_format_in_url}/
  102 + match 'myprofile/:profile/:controller(/:action(/:id))', :controller => Noosfero.pattern_for_controllers_in_directory('my_profile'), :profile => /#{Noosfero.identifier_format_in_url}/, :as => :myprofile
103 103
104 104
105 ###################################################### 105 ######################################################
@@ -127,14 +127,14 @@ Noosfero::Application.routes.draw do @@ -127,14 +127,14 @@ Noosfero::Application.routes.draw do
127 # cache stuff - hack 127 # cache stuff - hack
128 match 'public/:action/:id', :controller => 'public' 128 match 'public/:action/:id', :controller => 'public'
129 129
130 - match ':profile/*page/versions', :controller => 'content_viewer', :action => 'article_versions', :profile => /#{Noosfero.identifier_format}/, :constraints => EnvironmentDomainConstraint.new 130 + match ':profile/*page/versions', :controller => 'content_viewer', :action => 'article_versions', :profile => /#{Noosfero.identifier_format_in_url}/, :constraints => EnvironmentDomainConstraint.new
131 match '*page/versions', :controller => 'content_viewer', :action => 'article_versions' 131 match '*page/versions', :controller => 'content_viewer', :action => 'article_versions'
132 132
133 - match ':profile/*page/versions_diff', :controller => 'content_viewer', :action => 'versions_diff', :profile => /#{Noosfero.identifier_format}/, :constraints => EnvironmentDomainConstraint.new 133 + match ':profile/*page/versions_diff', :controller => 'content_viewer', :action => 'versions_diff', :profile => /#{Noosfero.identifier_format_in_url}/, :constraints => EnvironmentDomainConstraint.new
134 match '*page/versions_diff', :controller => 'content_viewer', :action => 'versions_diff' 134 match '*page/versions_diff', :controller => 'content_viewer', :action => 'versions_diff'
135 135
136 # match requests for profiles that don't have a custom domain 136 # match requests for profiles that don't have a custom domain
137 - match ':profile(/*page)', :controller => 'content_viewer', :action => 'view_page', :profile => /#{Noosfero.identifier_format}/, :constraints => EnvironmentDomainConstraint.new 137 + match ':profile(/*page)', :controller => 'content_viewer', :action => 'view_page', :profile => /#{Noosfero.identifier_format_in_url}/, :constraints => EnvironmentDomainConstraint.new
138 138
139 # match requests for content in domains hosted for profiles 139 # match requests for content in domains hosted for profiles
140 match '/(*page)', :controller => 'content_viewer', :action => 'view_page' 140 match '/(*page)', :controller => 'content_viewer', :action => 'view_page'
db/migrate/20150203143051_add_reference_to_role.rb 0 → 100644
@@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
  1 +class AddReferenceToRole < ActiveRecord::Migration
  2 + def self.up
  3 + add_column :roles, :profile_id, :integer
  4 + end
  5 + def self.down
  6 + remove_column :roles , :profile_id
  7 + end
  8 +end
db/migrate/20150210143723_add_custom_roles_permission_to_admin_roles.rb 0 → 100644
@@ -0,0 +1,18 @@ @@ -0,0 +1,18 @@
  1 +class AddCustomRolesPermissionToAdminRoles < ActiveRecord::Migration
  2 + def self.up
  3 + environment_admin = Role.find_by_key("environment_administrator")
  4 + profile_admin = Role.find_by_key("profile_admin")
  5 + environment_admin.permissions.append("manage_custom_roles")
  6 + profile_admin.permissions.append("manage_custom_roles")
  7 + environment_admin.save!
  8 + profile_admin.save!
  9 + end
  10 + def self.down
  11 + environment_admin = Role.find_by_key("environment_administrator")
  12 + profile_admin = Role.find_by_key("profile_admin")
  13 + environment_admin.permissions.delete("manage_custom_roles")
  14 + profile_admin.permissions.delete("manage_custom_roles")
  15 + environment_admin.save!
  16 + profile_admin.save!
  17 + end
  18 +end
db/migrate/20150423144533_add_new_box_to_every_environment_and_profile.rb 0 → 100644
@@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
  1 +class AddNewBoxToEveryEnvironmentAndProfile < ActiveRecord::Migration
  2 + def up
  3 + Environment.find_each do |env|
  4 + env.boxes << Box.new if env.boxes.count < 4
  5 + end
  6 +
  7 + Profile.find_each do |profile|
  8 + profile.boxes << Box.new if profile.boxes.count < 4
  9 + end
  10 + end
  11 +
  12 + def down
  13 + say "this migration can't be reverted"
  14 + end
  15 +end
@@ -593,6 +593,7 @@ ActiveRecord::Schema.define(:version =&gt; 20150408231524) do @@ -593,6 +593,7 @@ ActiveRecord::Schema.define(:version =&gt; 20150408231524) do
593 t.boolean "system", :default => false 593 t.boolean "system", :default => false
594 t.text "permissions" 594 t.text "permissions"
595 t.integer "environment_id" 595 t.integer "environment_id"
  596 + t.integer "profile_id"
596 end 597 end
597 598
598 create_table "scraps", :force => true do |t| 599 create_table "scraps", :force => true do |t|
debian/changelog
  1 +noosfero (1.2~0) UNRELEASED; urgency=medium
  2 +
  3 + * Temporary version in heavy development
  4 +
  5 + -- Antonio Terceiro <terceiro@debian.org> Fri, 08 May 2015 16:08:18 -0300
  6 +
  7 +noosfero (1.1) wheezy; urgency=low
  8 +
  9 + * Noosfero 1.1 final release
  10 +
  11 + -- Antonio Terceiro <terceiro@colivre.coop.br> Mon, 04 May 2015 18:47:35 -0300
  12 +
1 noosfero (1.1~rc4) wheezy; urgency=medium 13 noosfero (1.1~rc4) wheezy; urgency=medium
2 14
3 * Fourth release candidate for Noosfero 1.1 15 * Fourth release candidate for Noosfero 1.1
debian/control
@@ -14,8 +14,8 @@ Build-Depends: cucumber, @@ -14,8 +14,8 @@ Build-Depends: cucumber,
14 ruby-database-cleaner, 14 ruby-database-cleaner,
15 ruby-gettext, 15 ruby-gettext,
16 ruby-mocha, 16 ruby-mocha,
17 - ruby-rspec,  
18 - ruby-rspec-rails, 17 + ruby-rspec (>= 2.14),
  18 + ruby-rspec-rails (>= 2.14),
19 ruby-selenium-webdriver, 19 ruby-selenium-webdriver,
20 ruby-sqlite3, 20 ruby-sqlite3,
21 ruby-tidy, 21 ruby-tidy,
@@ -59,7 +59,9 @@ Depends: adduser, @@ -59,7 +59,9 @@ Depends: adduser,
59 ruby-redcloth, 59 ruby-redcloth,
60 ruby-rest-client, 60 ruby-rest-client,
61 ruby-rmagick, 61 ruby-rmagick,
  62 + ruby-sass-rails,
62 ruby-tzinfo (>= 1.1.0-2~), 63 ruby-tzinfo (>= 1.1.0-2~),
  64 + ruby-uglifier,
63 ruby-whenever, 65 ruby-whenever,
64 ruby-will-paginate (>= 2.3.12-1~), 66 ruby-will-paginate (>= 2.3.12-1~),
65 tango-icon-theme, 67 tango-icon-theme,
debian/noosfero.install
@@ -25,6 +25,7 @@ etc/init.d/noosfero etc/init.d @@ -25,6 +25,7 @@ etc/init.d/noosfero etc/init.d
25 etc/logrotate.d/noosfero etc/logrotate.d 25 etc/logrotate.d/noosfero etc/logrotate.d
26 etc/noosfero/varnish-accept-language.vcl etc/noosfero 26 etc/noosfero/varnish-accept-language.vcl etc/noosfero
27 etc/noosfero/varnish-noosfero.vcl etc/noosfero 27 etc/noosfero/varnish-noosfero.vcl etc/noosfero
  28 +etc/awstats-noosfero.conf etc/noosfero
28 lib usr/share/noosfero 29 lib usr/share/noosfero
29 locale usr/share/noosfero 30 locale usr/share/noosfero
30 plugins usr/share/noosfero 31 plugins usr/share/noosfero
features/change_appearance.feature 0 → 100644
@@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
  1 +Feature: Change appearance
  2 + As a user
  3 + I want to change the appearance of my profile page
  4 +
  5 + Background:
  6 + Given the following users
  7 + | login | name |
  8 + | joaosilva | Joao Silva |
  9 +
  10 + Scenario: Change appearance from default(3 boxes) to Left Top and Right(4 boxes)
  11 + Given I am logged in as "joaosilva"
  12 + And I go to joaosilva's control panel
  13 + And I follow "Edit sideboxes"
  14 + And I should not see an element ".box-4"
  15 + And I go to joaosilva's control panel
  16 + And I follow "Edit Appearance"
  17 + And I follow "Left Top and Right"
  18 + And I go to joaosilva's control panel
  19 + And I follow "Edit sideboxes"
  20 + And I should see an element ".box-4"
features/signup.feature
@@ -267,32 +267,6 @@ Feature: signup @@ -267,32 +267,6 @@ Feature: signup
267 Then I should be on the homepage 267 Then I should be on the homepage
268 268
269 @selenium 269 @selenium
270 - Scenario: join community on signup  
271 - Given the following users  
272 - | login | name |  
273 - | mariasilva | Maria Silva |  
274 - And the following communities  
275 - | name | identifier | owner |  
276 - | Free Software | freesoftware | mariasilva |  
277 - And feature "skip_new_user_email_confirmation" is disabled on environment  
278 - And I am on /freesoftware  
279 - When I follow "Join"  
280 - And I follow "New user"  
281 - And I fill in the following within ".no-boxes":  
282 - | e-Mail | josesilva@example.com |  
283 - | Username | josesilva |  
284 - | Password | secret |  
285 - | Password confirmation | secret |  
286 - | Full name | José da Silva |  
287 - And wait for the captcha signup time  
288 - And I press "Create my account"  
289 - And I go to josesilva's confirmation URL  
290 - And I fill in "Username" with "josesilva"  
291 - And I fill in "Password" with "secret"  
292 - And I press "Log in"  
293 - Then "José da Silva" should be a member of "Free Software"  
294 -  
295 - @selenium  
296 Scenario: user registration is moderated by admin 270 Scenario: user registration is moderated by admin
297 Given feature "admin_must_approve_new_users" is enabled on environment 271 Given feature "admin_must_approve_new_users" is enabled on environment
298 And feature "skip_new_user_email_confirmation" is disabled on environment 272 And feature "skip_new_user_email_confirmation" is disabled on environment
features/step_definitions/noosfero_steps.rb
@@ -94,8 +94,8 @@ Given /^the following blocks$/ do |table| @@ -94,8 +94,8 @@ Given /^the following blocks$/ do |table|
94 owner.boxes<< Box.new 94 owner.boxes<< Box.new
95 owner.boxes.first.blocks << MainBlock.new 95 owner.boxes.first.blocks << MainBlock.new
96 end 96 end
97 - box_id = owner.boxes.last.id  
98 - klass.constantize.create!(item.merge(:box_id => box_id)) 97 + box = owner.boxes.where(:position => 3).first
  98 + klass.constantize.create!(item.merge(:box => box))
99 end 99 end
100 end 100 end
101 101
lib/authenticated_system.rb
@@ -60,7 +60,11 @@ module AuthenticatedSystem @@ -60,7 +60,11 @@ module AuthenticatedSystem
60 if logged_in? && authorized? 60 if logged_in? && authorized?
61 true 61 true
62 else 62 else
63 - access_denied 63 + if params[:require_login_popup]
  64 + render :json => { :require_login_popup => true }
  65 + else
  66 + access_denied
  67 + end
64 end 68 end
65 end 69 end
66 70
lib/noosfero.rb
@@ -57,6 +57,12 @@ module Noosfero @@ -57,6 +57,12 @@ module Noosfero
57 '[a-z0-9][a-z0-9~.]*([_\-][a-z0-9~.]+)*' 57 '[a-z0-9][a-z0-9~.]*([_\-][a-z0-9~.]+)*'
58 end 58 end
59 59
  60 + # All valid identifiers, plus ~ meaning "the current user". See
  61 + # ApplicationController#redirect_to_current_user
  62 + def self.identifier_format_in_url
  63 + "(#{identifier_format}|~)"
  64 + end
  65 +
60 def self.default_hostname 66 def self.default_hostname
61 Environment.table_exists? && Environment.default ? Environment.default.default_hostname : 'localhost' 67 Environment.table_exists? && Environment.default ? Environment.default.default_hostname : 'localhost'
62 end 68 end
lib/noosfero/plugin.rb
@@ -8,6 +8,10 @@ class Noosfero::Plugin @@ -8,6 +8,10 @@ class Noosfero::Plugin
8 self.context = context 8 self.context = context
9 end 9 end
10 10
  11 + def environment
  12 + context.environment if self.context
  13 + end
  14 +
11 class << self 15 class << self
12 16
13 attr_writer :should_load 17 attr_writer :should_load
@@ -35,6 +39,7 @@ class Noosfero::Plugin @@ -35,6 +39,7 @@ class Noosfero::Plugin
35 # filters must be loaded after all extensions 39 # filters must be loaded after all extensions
36 klasses.each do |plugin| 40 klasses.each do |plugin|
37 load_plugin_filters plugin 41 load_plugin_filters plugin
  42 + load_plugin_hotspots plugin
38 end 43 end
39 end 44 end
40 45
@@ -108,6 +113,23 @@ class Noosfero::Plugin @@ -108,6 +113,23 @@ class Noosfero::Plugin
108 end 113 end
109 end 114 end
110 115
  116 + # This is a generic method to extend the hotspots list with plugins
  117 + # hotspots. This allows plugins to extend other plugins.
  118 + # To use this, the plugin must define its hotspots inside a module Hotspots.
  119 + # Its also needed to include Noosfero::Plugin::HotSpot module
  120 + # in order to dispatch plugins methods.
  121 + #
  122 + # Checkout FooPlugin for usage example.
  123 + def load_plugin_hotspots(plugin)
  124 + ActionDispatch::Reloader.to_prepare do
  125 + begin
  126 + module_name = "#{plugin.name}::Hotspots"
  127 + Noosfero::Plugin.send(:include, module_name.constantize)
  128 + rescue NameError
  129 + end
  130 + end
  131 + end
  132 +
111 def add_controller_filters(controller_class, plugin, filters) 133 def add_controller_filters(controller_class, plugin, filters)
112 unless filters.is_a?(Array) 134 unless filters.is_a?(Array)
113 filters = [filters] 135 filters = [filters]
lib/noosfero/version.rb
1 module Noosfero 1 module Noosfero
2 PROJECT = 'noosfero' 2 PROJECT = 'noosfero'
3 - VERSION = '1.1~rc4' 3 + VERSION = '1.2~0'
4 end 4 end
5 5
6 root = File.expand_path(File.dirname(__FILE__) + '/../..') 6 root = File.expand_path(File.dirname(__FILE__) + '/../..')
lib/tasks/backup.rake
1 -desc "Creates a backup of the user files stored in public/"  
2 -task :backup do  
3 - dirs = Dir.glob('public/images/[0-9][0-9][0-9][0-9]') + ['public/articles', 'public/thumbnails', 'public/user_themes'].select { |d| File.exists?(d) }  
4 - tarball = 'backups/files-' + Time.now.strftime('%Y-%m-%d-%R') + '.tar' 1 +task :load_backup_config do
  2 + $config = YAML.load_file('config/database.yml')
  3 +end
  4 +
  5 +task :check_backup_support => :load_backup_config do
  6 + if $config['production']['adapter'] != 'postgresql'
  7 + fail("Only PostgreSQL is supported for backups at the moment")
  8 + end
  9 +end
  10 +
  11 +backup_dirs = [
  12 + 'public/image_uploads',
  13 + 'public/articles',
  14 + 'public/thumbnails',
  15 + 'public/user_themes',
  16 +]
  17 +
  18 +desc "Creates a backup of the database and uploaded files"
  19 +task :backup => :check_backup_support do
  20 + dirs = backup_dirs.select { |d| File.exists?(d) }
  21 +
  22 + backup_name = Time.now.strftime('%Y-%m-%d-%R')
  23 + backup_file = File.join('tmp/backup', backup_name) + '.tar.gz'
  24 + mkdir_p 'tmp/backup'
  25 + dump = File.join('tmp/backup', backup_name) + '.sql'
  26 +
  27 + database = $config['production']['database']
  28 + host = $config['production']['host']
  29 + sh "pg_dump -h #{host} #{database} > #{dump}"
  30 +
  31 + sh 'tar', 'chaf', backup_file, dump, *dirs
  32 + rm_f dump
  33 +
  34 + puts "****************************************************"
  35 + puts "Backup in #{backup_file} !"
  36 + puts
  37 + puts "To restore, use:"
  38 + puts "$ rake restore BACKUP=#{backup_file}"
  39 + puts "****************************************************"
  40 +end
  41 +
  42 +def invalid_backup!(message, items=[])
  43 + puts "E: #{message}"
  44 + items.each do |i|
  45 + puts "E: - #{i}"
  46 + end
  47 + puts "E: Is this a backup archive created by Noosfero with \`rake backup\`?"
  48 + exit 1
  49 +end
  50 +
  51 +desc "Restores a backup created previousy with \`rake backup\`"
  52 +task :restore => :check_backup_support do
  53 + backup = ENV["BACKUP"]
  54 + unless backup
  55 + puts "usage: rake restore BACKUP=/path/to/backup"
  56 + exit 1
  57 + end
  58 +
  59 + files = `tar taf #{backup}`.split
  60 +
  61 + # validate files in the backup
  62 + invalid_files = []
  63 + files.each do |f|
  64 + if f !~ /tmp\/backup\// && (backup_dirs.none? { |d| f =~ /^#{d}\// })
  65 + invalid_files << f
  66 + end
  67 + end
  68 + if invalid_files.size > 0
  69 + invalid_backup!("Invalid files found in the backup archive", invalid_files)
  70 + end
  71 +
  72 + # find database dump in the archive
  73 + dumps = files.select do |f|
  74 + File.dirname(f) == 'tmp/backup' && f =~ /\.sql$/
  75 + end
  76 + if dumps.size == 0
  77 + invalid_backup!("Could not find a database dump in the archive.")
  78 + elsif dumps.size > 1
  79 + invalid_backup!("Multiple database dumps found in the archive:", dumps)
  80 + end
  81 + dump = dumps.first
  82 +
  83 + database = $config['production']['database']
  84 + username = $config['production']['username']
  85 + host = $config['production']['host']
  86 +
  87 + puts "WARNING: backups should be restored to an empty database, otherwise"
  88 + puts "data from the backup may not be loaded properly."
  89 + puts
  90 + puts 'You can remove the existing database and create a new one with:'
  91 + puts
  92 + puts "$ sudo -u postgres dropdb -h #{host} #{database}"
  93 + puts "$ sudo -u postgres createdb -h #{host} #{database} --owner #{username}"
  94 + puts
  95 + print "Are you sure you want to continue (y/N)? "
  96 + response = $stdin.gets.strip
  97 + unless ['y', 'yes'].include?(response.downcase)
  98 + puts "*** ABORTED."
  99 + exit 1
  100 + end
  101 +
  102 + sh 'tar', 'xaf', backup
  103 + sh "rails dbconsole production < #{dump}"
  104 + rm_f dump
5 105
6 - mkdir_p(File.dirname(tarball))  
7 - sh('tar', 'cf', tarball, *dirs) 106 + puts "****************************************************"
  107 + puts "Backup restored!"
  108 + puts "****************************************************"
8 end 109 end
lib/tasks/doc.rake
@@ -12,9 +12,8 @@ namespace :noosfero do @@ -12,9 +12,8 @@ namespace :noosfero do
12 end 12 end
13 end 13 end
14 task :unlink_plugins_textiles do 14 task :unlink_plugins_textiles do
15 - root = Pathname.new(File.dirname(__FILE__) + '/../..').expand_path  
16 - rm_f Dir.glob(root.join('doc/noosfero/plugins/*.textile')) -  
17 - [root.join('doc/noosfero/plugins/index.textile')] 15 + rm_f Dir.glob('doc/noosfero/plugins/*.textile') -
  16 + ['doc/noosfero/plugins/index.textile']
18 end 17 end
19 input = Dir.glob('doc/noosfero/**/*.textile') + plugins_textiles.map{|i| "doc/noosfero/plugins/#{File.basename(i)}"} 18 input = Dir.glob('doc/noosfero/**/*.textile') + plugins_textiles.map{|i| "doc/noosfero/plugins/#{File.basename(i)}"}
20 topics_xhtml = input.map { |item| item.sub('.textile', '.en.xhtml') }.uniq 19 topics_xhtml = input.map { |item| item.sub('.textile', '.en.xhtml') }.uniq
lib/tasks/error_messages.rake
@@ -4,7 +4,7 @@ targets = [] @@ -4,7 +4,7 @@ targets = []
4 templates.each do |template| 4 templates.each do |template|
5 target = template.gsub(/.erb$/, '') 5 target = template.gsub(/.erb$/, '')
6 targets << target 6 targets << target
7 - file target => [:makemo, template] do 7 + file target => [:makemo, template, :environment] do
8 require 'erb' 8 require 'erb'
9 erb = ERB.new(File.read(template)) 9 erb = ERB.new(File.read(template))
10 File.open(target, 'w') do |file| 10 File.open(target, 'w') do |file|
plugins/event/po/pt/event.po
@@ -5,8 +5,8 @@ @@ -5,8 +5,8 @@
5 # 5 #
6 msgid "" 6 msgid ""
7 msgstr "" 7 msgstr ""
8 -"Project-Id-Version: 1.0-690-gcb6e853\n"  
9 -"POT-Creation-Date: 2015-03-05 12:09-0300\n" 8 +"Project-Id-Version: 1.1~rc4\n"
  9 +"POT-Creation-Date: 2015-04-20 19:44-0300\n"
10 "PO-Revision-Date: 2015-01-30 00:18-0000\n" 10 "PO-Revision-Date: 2015-01-30 00:18-0000\n"
11 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n" 11 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
12 "Language-Team: LANGUAGE <LL@li.org>\n" 12 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -16,61 +16,53 @@ msgstr &quot;&quot; @@ -16,61 +16,53 @@ msgstr &quot;&quot;
16 "Content-Transfer-Encoding: 8bit\n" 16 "Content-Transfer-Encoding: 8bit\n"
17 "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" 17 "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n"
18 18
  19 +#: plugins/event/lib/event_plugin.rb:4
  20 +msgid "Event Extras"
  21 +msgstr "Extras para Eventos"
  22 +
  23 +#: plugins/event/lib/event_plugin.rb:8
  24 +msgid ""
  25 +"Include a new block to show the environment's or profiles' events information"
  26 +msgstr ""
  27 +"Adiciona um novo bloco para apresentar as informações de eventos do ambiente "
  28 +"ou dos perfis"
  29 +
19 #: plugins/event/lib/event_plugin/event_block.rb:12 30 #: plugins/event/lib/event_plugin/event_block.rb:12
20 msgid "Events" 31 msgid "Events"
21 msgstr "Eventos" 32 msgstr "Eventos"
22 33
23 #: plugins/event/lib/event_plugin/event_block.rb:16 34 #: plugins/event/lib/event_plugin/event_block.rb:16
24 msgid "Show the profile events or all environment events." 35 msgid "Show the profile events or all environment events."
25 -msgstr "Mostrar todos os eventos." 36 +msgstr "Mostra todos os eventos de um perfil ou do ambiente."
26 37
27 #: plugins/event/lib/event_plugin/event_block.rb:65 38 #: plugins/event/lib/event_plugin/event_block.rb:65
28 -#, fuzzy  
29 msgid "One month ago" 39 msgid "One month ago"
30 msgid_plural "%d months ago" 40 msgid_plural "%d months ago"
31 -msgstr[0] "Iniciou a um mês atrás."  
32 -msgstr[1] "Iniciou a %d meses atrás." 41 +msgstr[0] "Um mês atrás"
  42 +msgstr[1] "%d meses atrás."
33 43
34 #: plugins/event/lib/event_plugin/event_block.rb:67 44 #: plugins/event/lib/event_plugin/event_block.rb:67
35 msgid "Yesterday" 45 msgid "Yesterday"
36 msgid_plural "%d days ago" 46 msgid_plural "%d days ago"
37 -msgstr[0] ""  
38 -msgstr[1] "" 47 +msgstr[0] "Ontem"
  48 +msgstr[1] "%d dias atrás"
39 49
40 #: plugins/event/lib/event_plugin/event_block.rb:69 50 #: plugins/event/lib/event_plugin/event_block.rb:69
41 msgid "Today" 51 msgid "Today"
42 -msgstr "" 52 +msgstr "Hoje"
43 53
44 #: plugins/event/lib/event_plugin/event_block.rb:71 54 #: plugins/event/lib/event_plugin/event_block.rb:71
45 msgid "Tomorrow" 55 msgid "Tomorrow"
46 msgid_plural "%d days left to start" 56 msgid_plural "%d days left to start"
47 -msgstr[0] ""  
48 -msgstr[1] "" 57 +msgstr[0] "Amanhã"
  58 +msgstr[1] "%d dias para começar"
49 59
50 #: plugins/event/lib/event_plugin/event_block.rb:73 60 #: plugins/event/lib/event_plugin/event_block.rb:73
51 -#, fuzzy  
52 msgid "One month left to start" 61 msgid "One month left to start"
53 msgid_plural "%d months left to start" 62 msgid_plural "%d months left to start"
54 msgstr[0] "Um mês para iniciar" 63 msgstr[0] "Um mês para iniciar"
55 msgstr[1] "% meses para iniciar" 64 msgstr[1] "% meses para iniciar"
56 65
57 -#: plugins/event/lib/event_plugin.rb:4  
58 -msgid "Event Extras"  
59 -msgstr "Eventos"  
60 -  
61 -#: plugins/event/lib/event_plugin.rb:8  
62 -msgid ""  
63 -"Include a new block to show the environment's or profiles' events information"  
64 -msgstr ""  
65 -"Adiciona um novo bloco para apresentar as informações de eventos do ambiente "  
66 -"ou de perfis"  
67 -  
68 -#: plugins/event/views/event_plugin/event_block_item.html.erb:6  
69 -msgid "Duration: 1 day"  
70 -msgid_plural "Duration: %s days"  
71 -msgstr[0] ""  
72 -msgstr[1] ""  
73 -  
74 #: plugins/event/views/profile_design/event_plugin/_event_block.html.erb:1 66 #: plugins/event/views/profile_design/event_plugin/_event_block.html.erb:1
75 msgid "Limit of items" 67 msgid "Limit of items"
76 msgstr "Limite de itens" 68 msgstr "Limite de itens"
@@ -94,12 +86,17 @@ msgstr &quot;Mostrar apenas eventos futuros&quot; @@ -94,12 +86,17 @@ msgstr &quot;Mostrar apenas eventos futuros&quot;
94 86
95 #: plugins/event/views/profile_design/event_plugin/_event_block.html.erb:22 87 #: plugins/event/views/profile_design/event_plugin/_event_block.html.erb:22
96 msgid "Limit of days to display" 88 msgid "Limit of days to display"
97 -msgstr "Limite de dias de distância para mostrar eventos" 89 +msgstr "Limite de dias para mostrar"
98 90
99 #: plugins/event/views/profile_design/event_plugin/_event_block.html.erb:24 91 #: plugins/event/views/profile_design/event_plugin/_event_block.html.erb:24
100 -#, fuzzy  
101 msgid "Only show events in this interval of days." 92 msgid "Only show events in this interval of days."
102 -msgstr "Mostar somente eventos que acontecem dentro do limite de dias" 93 +msgstr "Mostar somente os eventos nesse intervalo de dias"
  94 +
  95 +#: plugins/event/views/event_plugin/event_block_item.html.erb:6
  96 +msgid "Duration: 1 day"
  97 +msgid_plural "Duration: %s days"
  98 +msgstr[0] "Duração: 1 dia"
  99 +msgstr[1] "Duração: %s dias"
103 100
104 #~ msgid "Started one day ago." 101 #~ msgid "Started one day ago."
105 #~ msgid_plural "Started %d days ago." 102 #~ msgid_plural "Started %d days ago."
plugins/foo/lib/foo_plugin.rb
1 class FooPlugin < Noosfero::Plugin 1 class FooPlugin < Noosfero::Plugin
  2 + include Noosfero::Plugin::HotSpot
2 3
3 def self.plugin_name 4 def self.plugin_name
4 "Foo" 5 "Foo"
@@ -8,12 +9,29 @@ class FooPlugin &lt; Noosfero::Plugin @@ -8,12 +9,29 @@ class FooPlugin &lt; Noosfero::Plugin
8 _("A sample plugin to test autoload craziness.") 9 _("A sample plugin to test autoload craziness.")
9 end 10 end
10 11
  12 + module Hotspots
  13 + # -> Custom foo plugin hotspot
  14 + # do something to extend the FooPlugin behaviour
  15 + # receive params a, b and c
  16 + # returns = boolean or something else
  17 + def foo_plugin_my_hotspot(a, b, c)
  18 + end
  19 +
  20 + # -> Custom title for foo profiles tab
  21 + # returns = a string with a custom title
  22 + def foo_plugin_tab_title
  23 + end
  24 + end
  25 +
11 def control_panel_buttons 26 def control_panel_buttons
12 {:title => 'Foo plugin button', :icon => '', :url => ''} 27 {:title => 'Foo plugin button', :icon => '', :url => ''}
13 end 28 end
14 29
15 def profile_tabs 30 def profile_tabs
16 - {:title => 'Foo plugin tab', :id => 'foo_plugin', :content => lambda {'Foo plugin random content'} } 31 + title = plugins.dispatch_first(:foo_plugin_tab_title)
  32 + title = 'Foo plugin tab' unless title
  33 +
  34 + {:title => title, :id => 'foo_plugin', :content => lambda {'Foo plugin random content'} }
17 end 35 end
18 36
19 end 37 end
plugins/foo/test/unit/foo_plugin_test.rb
@@ -4,7 +4,25 @@ class FooPluginTest &lt; ActiveSupport::TestCase @@ -4,7 +4,25 @@ class FooPluginTest &lt; ActiveSupport::TestCase
4 def test_foo 4 def test_foo
5 FooPlugin::Bar.create! 5 FooPlugin::Bar.create!
6 end 6 end
  7 +
7 def test_monkey_patch 8 def test_monkey_patch
8 Profile.new.bar 9 Profile.new.bar
9 end 10 end
  11 +
  12 + should "respond to new hotspots" do
  13 + plugin = FooPlugin.new
  14 +
  15 + assert plugin.respond_to?(:foo_plugin_my_hotspot)
  16 + assert plugin.respond_to?(:foo_plugin_tab_title)
  17 + end
  18 +
  19 + should "other plugin respond to new hotspots" do
  20 + class TestPlugin < Noosfero::Plugin
  21 + end
  22 +
  23 + plugin = TestPlugin.new
  24 +
  25 + assert plugin.respond_to?(:foo_plugin_my_hotspot)
  26 + assert plugin.respond_to?(:foo_plugin_tab_title)
  27 + end
10 end 28 end
plugins/google_analytics/lib/ext/profile.rb
@@ -2,4 +2,9 @@ require_dependency &#39;profile&#39; @@ -2,4 +2,9 @@ require_dependency &#39;profile&#39;
2 2
3 class Profile 3 class Profile
4 settings_items :google_analytics_profile_id 4 settings_items :google_analytics_profile_id
  5 + attr_accessible :google_analytics_profile_id
  6 +
  7 + descendants.each do |descendant|
  8 + descendant.attr_accessible :google_analytics_profile_id
  9 + end
5 end 10 end
plugins/google_analytics/lib/google_analytics_plugin.rb
@@ -19,12 +19,15 @@ class GoogleAnalyticsPlugin &lt; Noosfero::Plugin @@ -19,12 +19,15 @@ class GoogleAnalyticsPlugin &lt; Noosfero::Plugin
19 19
20 def head_ending 20 def head_ending
21 unless profile_id.blank? 21 unless profile_id.blank?
22 - expanded_template('tracking-code.rhtml',{:profile_id => profile_id}) 22 + expanded_template('tracking-code.html.erb',{:profile_id => profile_id})
23 end 23 end
24 end 24 end
25 25
26 def profile_editor_extras 26 def profile_editor_extras
27 - expanded_template('profile-editor-extras.rhtml',{:profile_id => profile_id}) 27 + analytics_id = profile_id
  28 + lambda {
  29 + render :file => 'profile-editor-extras', :locals => { :profile_id => analytics_id }
  30 + }
28 end 31 end
29 32
30 end 33 end
plugins/google_analytics/test/functional/profile_editor_controller_test.rb 0 → 100644
@@ -0,0 +1,31 @@ @@ -0,0 +1,31 @@
  1 +require 'test_helper'
  2 +require 'profile_editor_controller'
  3 +
  4 +# Re-raise errors caught by the controller.
  5 +class ProfileEditorController; def rescue_action(e) raise e end; end
  6 +
  7 +class ProfileEditorControllerTest < ActionController::TestCase
  8 +
  9 + def setup
  10 + @controller = ProfileEditorController.new
  11 + @request = ActionController::TestRequest.new
  12 + @response = ActionController::TestResponse.new
  13 + @profile = create_user('default_user').person
  14 + login_as(@profile.identifier)
  15 + Environment.default.enable_plugin(GoogleAnalyticsPlugin.name)
  16 + end
  17 +
  18 + attr_accessor :profile
  19 +
  20 + should 'add extra fields to profile editor info and settings' do
  21 + get :edit, :profile => profile.identifier
  22 + assert_tag_in_string @response.body, :tag => 'label', :content => /Google Analytics/, :attributes => { :for => 'profile_data_google_analytics_profile_id' }
  23 + assert_tag_in_string @response.body, :tag => 'input', :attributes => { :id => 'profile_data_google_analytics_profile_id' }
  24 + end
  25 +
  26 + should 'save code filled in on field' do
  27 + post :edit, :profile => profile.identifier, :profile_data => {:google_analytics_profile_id => 12345678}
  28 + assert_equal '12345678', Person.find(profile.id).google_analytics_profile_id
  29 + end
  30 +
  31 +end
plugins/google_analytics/test/unit/google_analytics_plugin_test.rb
@@ -27,11 +27,6 @@ class GoogleAnalyticsPluginTest &lt; ActiveSupport::TestCase @@ -27,11 +27,6 @@ class GoogleAnalyticsPluginTest &lt; ActiveSupport::TestCase
27 assert_equal 'content', @plugin.head_ending 27 assert_equal 'content', @plugin.head_ending
28 end 28 end
29 29
30 - should 'add extra fields to profile editor info and settings' do  
31 - assert_tag_in_string @plugin.profile_editor_extras,  
32 - :tag => 'input', :attributes => {:id => 'profile_data_google_analytics_profile_id', :value => 10}  
33 - end  
34 -  
35 should 'extends Profile with attr google_analytics_profile_id' do 30 should 'extends Profile with attr google_analytics_profile_id' do
36 assert_respond_to Profile.new, :google_analytics_profile_id 31 assert_respond_to Profile.new, :google_analytics_profile_id
37 end 32 end
plugins/google_analytics/views/profile-editor-extras.html.erb 0 → 100644
@@ -0,0 +1,3 @@ @@ -0,0 +1,3 @@
  1 +<h2><%= c_('Statistics') %></h2>
  2 +<%= labelled_form_field(_('Google Analytics Profile ID'), text_field(:profile_data, :google_analytics_profile_id, :value => profile_id)) %>
  3 +<%= link_to(_('See how to configure statistics for your profile'), '/doc/plugins/google_analytics', :target => '_blank') %>
plugins/google_analytics/views/profile-editor-extras.rhtml
@@ -1,5 +0,0 @@ @@ -1,5 +0,0 @@
1 -<% extend ApplicationHelper %>  
2 -  
3 -<h2><%= c_('Statistics') %></h2>  
4 -<%= labelled_form_field(_('Google Analytics Profile ID'), text_field(:profile_data, :google_analytics_profile_id, :value => profile_id)) %>  
5 -<%= link_to(_('See how to configure statistics for your profile'), '/doc/plugins/google_analytics', :target => '_blank') %>  
plugins/google_analytics/views/tracking-code.html.erb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +<script>
  2 + (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
  3 + (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
  4 + m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
  5 + })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
  6 +
  7 + ga('create', '<%= escape_javascript locals[:profile_id] %>', 'auto');
  8 + ga('send', 'pageview');
  9 +</script>
plugins/google_analytics/views/tracking-code.rhtml
@@ -1,10 +0,0 @@ @@ -1,10 +0,0 @@
1 -<script type="text/javascript">  
2 - var _gaq = _gaq || [];  
3 - _gaq.push(['_setAccount', '<%= escape_javascript locals[:profile_id] %>']);  
4 - _gaq.push(['_trackPageview']);  
5 - (function() {  
6 - var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;  
7 - ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';  
8 - var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);  
9 - })();  
10 -</script>  
plugins/ldap/lib/ldap_authentication.rb
@@ -77,18 +77,20 @@ class LdapAuthentication @@ -77,18 +77,20 @@ class LdapAuthentication
77 end 77 end
78 78
79 def get_user_attributes_from_ldap_entry(entry) 79 def get_user_attributes_from_ldap_entry(entry)
80 - {  
81 - :dn => entry.dn,  
82 - :fullname => LdapAuthentication.get_attr(entry, self.attr_fullname),  
83 - :mail => LdapAuthentication.get_attr(entry, self.attr_mail),  
84 - } 80 + attributes = entry.instance_values["myhash"]
  81 +
  82 + attributes[:dn] = entry.dn
  83 + attributes[:fullname] = LdapAuthentication.get_attr(entry, self.attr_fullname)
  84 + attributes[:mail] = LdapAuthentication.get_attr(entry, self.attr_mail)
  85 +
  86 + attributes
85 end 87 end
86 88
87 # Return the attributes needed for the LDAP search. It will only 89 # Return the attributes needed for the LDAP search. It will only
88 # include the user attributes if on-the-fly registration is enabled 90 # include the user attributes if on-the-fly registration is enabled
89 def search_attributes 91 def search_attributes
90 if onthefly_register? 92 if onthefly_register?
91 - ['dn', self.attr_fullname, self.attr_mail] 93 + nil
92 else 94 else
93 ['dn'] 95 ['dn']
94 end 96 end
@@ -111,6 +113,7 @@ class LdapAuthentication @@ -111,6 +113,7 @@ class LdapAuthentication
111 end 113 end
112 login_filter = Net::LDAP::Filter.eq( self.attr_login, login ) 114 login_filter = Net::LDAP::Filter.eq( self.attr_login, login )
113 object_filter = Net::LDAP::Filter.eq( "objectClass", "*" ) 115 object_filter = Net::LDAP::Filter.eq( "objectClass", "*" )
  116 +
114 attrs = {} 117 attrs = {}
115 118
116 search_filter = object_filter & login_filter 119 search_filter = object_filter & login_filter
plugins/ldap/lib/ldap_plugin.rb
1 require File.dirname(__FILE__) + '/ldap_authentication.rb' 1 require File.dirname(__FILE__) + '/ldap_authentication.rb'
2 2
3 class LdapPlugin < Noosfero::Plugin 3 class LdapPlugin < Noosfero::Plugin
  4 + include Noosfero::Plugin::HotSpot
4 5
5 def self.plugin_name 6 def self.plugin_name
6 "LdapPlugin" 7 "LdapPlugin"
@@ -10,6 +11,26 @@ class LdapPlugin &lt; Noosfero::Plugin @@ -10,6 +11,26 @@ class LdapPlugin &lt; Noosfero::Plugin
10 _("A plugin that add ldap support.") 11 _("A plugin that add ldap support.")
11 end 12 end
12 13
  14 + module Hotspots
  15 + # -> Custom ldap plugin hotspot to set profile data before user creation
  16 + # receive the followings params:
  17 + # - attrs with ldap received data
  18 + # - login received by ldap
  19 + # - params from current context
  20 + # returns = updated person_data hash
  21 + def ldap_plugin_set_profile_data(attrs, params)
  22 + [attrs, params]
  23 + end
  24 +
  25 + # -> Custom ldap plugin hotspot to update user object
  26 + # receive the followings params:
  27 + # - user: user object
  28 + # - attrs with ldap received data
  29 + # returns = none
  30 + def ldap_plugin_update_user(user, attrs)
  31 + end
  32 + end
  33 +
13 def allow_user_registration 34 def allow_user_registration
14 false 35 false
15 end 36 end
@@ -35,17 +56,22 @@ class LdapPlugin &lt; Noosfero::Plugin @@ -35,17 +56,22 @@ class LdapPlugin &lt; Noosfero::Plugin
35 56
36 if attrs 57 if attrs
37 user.login = login 58 user.login = login
38 - user.email = attrs[:mail] 59 + user.email = get_email(attrs, login)
39 user.name = attrs[:fullname] 60 user.name = attrs[:fullname]
40 user.password = password 61 user.password = password
41 user.password_confirmation = password 62 user.password_confirmation = password
42 - user.person_data = context.params[:profile_data] 63 + user.person_data = plugins.pipeline(:ldap_plugin_set_profile_data, attrs, context.params).last[:profile_data]
43 user.activated_at = Time.now.utc 64 user.activated_at = Time.now.utc
44 user.activation_code = nil 65 user.activation_code = nil
45 66
46 ldap = LdapAuthentication.new(context.environment.ldap_plugin_attributes) 67 ldap = LdapAuthentication.new(context.environment.ldap_plugin_attributes)
47 begin 68 begin
48 - user = nil unless user.save 69 + if user.save
  70 + user.activate
  71 + plugins.dispatch(:ldap_plugin_update_user, user, attrs)
  72 + else
  73 + user = nil
  74 + end
49 rescue 75 rescue
50 #User not saved 76 #User not saved
51 end 77 end
@@ -54,7 +80,6 @@ class LdapPlugin &lt; Noosfero::Plugin @@ -54,7 +80,6 @@ class LdapPlugin &lt; Noosfero::Plugin
54 end 80 end
55 81
56 else 82 else
57 -  
58 return nil if !user.activated? 83 return nil if !user.activated?
59 84
60 begin 85 begin
@@ -69,6 +94,16 @@ class LdapPlugin &lt; Noosfero::Plugin @@ -69,6 +94,16 @@ class LdapPlugin &lt; Noosfero::Plugin
69 user 94 user
70 end 95 end
71 96
  97 + def get_email(attrs, login)
  98 + return attrs[:mail] unless attrs[:mail].blank?
  99 +
  100 + if attrs[:fullname]
  101 + return attrs[:fullname].to_slug + "@ldap.user"
  102 + else
  103 + return login.to_slug + "@ldap.user"
  104 + end
  105 + end
  106 +
72 def login_extra_contents 107 def login_extra_contents
73 proc do 108 proc do
74 @person = Person.new(:environment => @environment) 109 @person = Person.new(:environment => @environment)
plugins/require_auth_to_comment/controllers/require_auth_to_comment_plugin_admin_controller.rb 0 → 100644
@@ -0,0 +1,14 @@ @@ -0,0 +1,14 @@
  1 +class RequireAuthToCommentPluginAdminController < AdminController
  2 +
  3 + def index
  4 + settings = params[:settings]
  5 + settings ||= {}
  6 + @settings = Noosfero::Plugin::Settings.new(environment, RequireAuthToCommentPlugin, settings)
  7 + if request.post?
  8 + @settings.save!
  9 + session[:notice] = 'Settings succefully saved.'
  10 + redirect_to :action => 'index'
  11 + end
  12 + end
  13 +
  14 +end
plugins/require_auth_to_comment/lib/require_auth_to_comment_plugin.rb
@@ -21,11 +21,20 @@ class RequireAuthToCommentPlugin &lt; Noosfero::Plugin @@ -21,11 +21,20 @@ class RequireAuthToCommentPlugin &lt; Noosfero::Plugin
21 end 21 end
22 22
23 def stylesheet? 23 def stylesheet?
24 - true 24 + !display_login_popup?
  25 + end
  26 +
  27 + def display_login_popup?
  28 + settings = Noosfero::Plugin::Settings.new(context.environment, self.class)
  29 + settings.require_type == 'display_login_popup'
  30 + end
  31 +
  32 + def self.require_type_default_setting
  33 + 'hide_button'
25 end 34 end
26 35
27 def js_files 36 def js_files
28 - ['hide_comment_form.js', 'jquery.livequery.min.js'] 37 + ['hide_comment_form.js', 'jquery.livequery.min.js'] + (display_login_popup? ? ['comment_require_login.js'] : [])
29 end 38 end
30 39
31 def body_beginning 40 def body_beginning
plugins/require_auth_to_comment/public/comment_require_login.js 0 → 100644
@@ -0,0 +1,8 @@ @@ -0,0 +1,8 @@
  1 +(function($) {
  2 + $(window).bind('userDataLoaded', function(event, data) {
  3 + if (!data.login && $('meta[name="profile.allow_unauthenticated_comments"]').length <= 0) {
  4 + $('.display-comment-form').unbind();
  5 + $('.display-comment-form').addClass('require-login-popup');
  6 + }
  7 + });
  8 +})(jQuery);
plugins/require_auth_to_comment/test/unit/require_auth_to_comment_plugin_test.rb
@@ -5,9 +5,10 @@ class RequireAuthToCommentPluginTest &lt; ActiveSupport::TestCase @@ -5,9 +5,10 @@ class RequireAuthToCommentPluginTest &lt; ActiveSupport::TestCase
5 def setup 5 def setup
6 @plugin = RequireAuthToCommentPlugin.new 6 @plugin = RequireAuthToCommentPlugin.new
7 @comment = Comment.new 7 @comment = Comment.new
  8 + @environment = fast_create(Environment)
8 end 9 end
9 10
10 - attr_reader :plugin, :comment 11 + attr_reader :plugin, :comment, :environment
11 12
12 should 'reject comments for unauthenticated users' do 13 should 'reject comments for unauthenticated users' do
13 plugin.context = logged_in(false) 14 plugin.context = logged_in(false)
@@ -29,6 +30,35 @@ class RequireAuthToCommentPluginTest &lt; ActiveSupport::TestCase @@ -29,6 +30,35 @@ class RequireAuthToCommentPluginTest &lt; ActiveSupport::TestCase
29 assert !comment.rejected? 30 assert !comment.rejected?
30 end 31 end
31 32
  33 + should 'the default require type setting be hide_button' do
  34 + assert_equal 'hide_button', plugin.class.require_type_default_setting
  35 + end
  36 +
  37 + should 'display_login_popup? be false by default' do
  38 + context = mock();
  39 + context.expects(:environment).returns(environment)
  40 + plugin.expects(:context).returns(context)
  41 + assert !plugin.display_login_popup?
  42 + end
  43 +
  44 + should 'display_login_popup? be true if require_type is defined as display_login_popup' do
  45 + context = mock();
  46 + context.expects(:environment).returns(environment)
  47 + environment[:settings] = {:require_auth_to_comment_plugin => {:require_type => "display_login_popup"}}
  48 + plugin.expects(:context).returns(context)
  49 + assert plugin.display_login_popup?
  50 + end
  51 +
  52 + should 'not display stylesheet if login popup is active' do
  53 + plugin.expects(:display_login_popup?).returns(true)
  54 + assert !plugin.stylesheet?
  55 + end
  56 +
  57 + should 'display stylesheet if login popup is inactive' do
  58 + plugin.expects(:display_login_popup?).returns(false)
  59 + assert plugin.stylesheet?
  60 + end
  61 +
32 protected 62 protected
33 63
34 def logged_in(boolean) 64 def logged_in(boolean)
plugins/require_auth_to_comment/views/require_auth_to_comment_plugin_admin/index.html.erb 0 → 100644
@@ -0,0 +1,20 @@ @@ -0,0 +1,20 @@
  1 +<h1><%= _('Require auth to comment Settings')%></h1>
  2 +
  3 +<%= form_for(:settings) do |f| %>
  4 +
  5 + <div class="require-type">
  6 + <strong>
  7 + <div class="hide-button">
  8 + <%= radio_button(:settings, :require_type, 'hide_button') %> <%= _('Hide button') %>
  9 + </div>
  10 + <div class="display-login-popup">
  11 + <%= radio_button(:settings, :require_type, 'display_login_popup') %> <%= _('Display login popup') %>
  12 + </div>
  13 + </strong>
  14 + </div>
  15 +
  16 + <% button_bar do %>
  17 + <%= submit_button(:save, _('Save'), :cancel => {:controller => 'plugins', :action => 'index'}) %>
  18 + <% end %>
  19 +
  20 +<% end %>
plugins/send_email/controllers/send_email_plugin_base_controller.rb
@@ -11,7 +11,8 @@ module SendEmailPluginBaseController @@ -11,7 +11,8 @@ module SendEmailPluginBaseController
11 ) 11 )
12 @mail.subject = params[:subject] unless params[:subject].blank? 12 @mail.subject = params[:subject] unless params[:subject].blank?
13 if @mail.valid? 13 if @mail.valid?
14 - SendEmailPlugin::Sender.send_message(request.referer, @context_url, @mail).deliver 14 + @referer = request.referer
  15 + SendEmailPlugin::Sender.send_message(@referer, @context_url, @mail).deliver
15 if request.xhr? 16 if request.xhr?
16 render :text => _('Message sent') 17 render :text => _('Message sent')
17 else 18 else
plugins/send_email/lib/send_email_plugin.rb
@@ -16,9 +16,9 @@ class SendEmailPlugin &lt; Noosfero::Plugin @@ -16,9 +16,9 @@ class SendEmailPlugin &lt; Noosfero::Plugin
16 16
17 def parse_content(html, source) 17 def parse_content(html, source)
18 if context.profile 18 if context.profile
19 - html.gsub!(/\{sendemail\}/, "/profile/#{context.profile.identifier}/plugin/send_email/deliver") 19 + html.gsub!(/({|%7[Bb])sendemail(}|%7[Dd])/, "/profile/#{context.profile.identifier}/plugin/send_email/deliver")
20 else 20 else
21 - html.gsub!(/\{sendemail\}/, '/plugin/send_email/deliver') 21 + html.gsub!(/({|%7[Bb])sendemail(}|%7[Dd])/, '/plugin/send_email/deliver')
22 end 22 end
23 [html, source] 23 [html, source]
24 end 24 end
plugins/send_email/lib/send_email_plugin/mail.rb
@@ -10,12 +10,11 @@ class SendEmailPlugin::Mail @@ -10,12 +10,11 @@ class SendEmailPlugin::Mail
10 validate :recipients_format 10 validate :recipients_format
11 11
12 def initialize(attributes = {:subject => 'New mail'}) 12 def initialize(attributes = {:subject => 'New mail'})
13 - @environment = attributes[:environment]  
14 - @from = attributes[:from]  
15 - @to = attributes[:to]  
16 - @subject = attributes[:subject]  
17 - @message = attributes[:message]  
18 - @params = attributes[:params] 13 + if attributes
  14 + attributes.each do |attr,value|
  15 + self.send("#{attr}=", value)
  16 + end
  17 + end
19 end 18 end
20 19
21 def recipients_format 20 def recipients_format
@@ -36,7 +35,7 @@ class SendEmailPlugin::Mail @@ -36,7 +35,7 @@ class SendEmailPlugin::Mail
36 end 35 end
37 36
38 def params=(value = {}) 37 def params=(value = {})
39 - [:action, :controller, :to, :message, :subject, :from].each{|k| value.delete(k)} 38 + [:profile, :action, :controller, :to, :message, :subject, :from, :commit].each{|k| value.delete(k)}
40 @params = value 39 @params = value
41 end 40 end
42 41
plugins/send_email/lib/send_email_plugin/sender.rb
@@ -7,9 +7,9 @@ class SendEmailPlugin::Sender &lt; Noosfero::Plugin::MailerBase @@ -7,9 +7,9 @@ class SendEmailPlugin::Sender &lt; Noosfero::Plugin::MailerBase
7 @params = mail.params 7 @params = mail.params
8 8
9 mail( 9 mail(
  10 + content_type: 'text/plain',
10 to: mail.to, 11 to: mail.to,
11 from: mail.from, 12 from: mail.from,
12 - body: mail.params,  
13 subject: "[#{mail.environment.name}] #{mail.subject}" 13 subject: "[#{mail.environment.name}] #{mail.subject}"
14 ) 14 )
15 end 15 end
plugins/send_email/test/functional/send_email_plugin_base_controller_test.rb
@@ -54,6 +54,13 @@ def run_common_tests @@ -54,6 +54,13 @@ def run_common_tests
54 post :deliver, @extra_args.merge(:to => 'john@example.com', :message => 'Hi john', :subject => 'Hello john') 54 post :deliver, @extra_args.merge(:to => 'john@example.com', :message => 'Hi john', :subject => 'Hello john')
55 assert_equal '[Colivre.net] Hello john', ActionMailer::Base.deliveries.first.subject 55 assert_equal '[Colivre.net] Hello john', ActionMailer::Base.deliveries.first.subject
56 end 56 end
  57 +
  58 + should 'deliver mail with message from view' do
  59 + Environment.any_instance.stubs(:send_email_plugin_allow_to).returns('john@example.com')
  60 + post :deliver, @extra_args.merge(:to => 'john@example.com', :message => 'Hi john', :subject => 'Hello john')
  61 + assert_match /Contact from/, ActionMailer::Base.deliveries.first.body.to_s
  62 + end
  63 +
57 end 64 end
58 65
59 class SendEmailPluginProfileControllerTest < ActionController::TestCase 66 class SendEmailPluginProfileControllerTest < ActionController::TestCase
plugins/send_email/test/unit/send_email_plugin_sender_test.rb
@@ -15,12 +15,14 @@ class SendEmailPluginSenderTest &lt; ActiveSupport::TestCase @@ -15,12 +15,14 @@ class SendEmailPluginSenderTest &lt; ActiveSupport::TestCase
15 end 15 end
16 16
17 should 'be able to deliver mail' do 17 should 'be able to deliver mail' do
  18 + @mail.expects(:params).returns({})
18 response = SendEmailPlugin::Sender.send_message("http://localhost/contact", 'http//profile', @mail) 19 response = SendEmailPlugin::Sender.send_message("http://localhost/contact", 'http//profile', @mail)
19 assert_equal 'noreply@localhost', response.from.join 20 assert_equal 'noreply@localhost', response.from.join
20 assert_equal "[Noosfero] #{@mail.subject}", response.subject 21 assert_equal "[Noosfero] #{@mail.subject}", response.subject
21 end 22 end
22 23
23 should 'deliver mail to john@example.com' do 24 should 'deliver mail to john@example.com' do
  25 + @mail.expects(:params).returns({})
24 response = SendEmailPlugin::Sender.send_message("http://localhost/contact", 'http//profile', @mail) 26 response = SendEmailPlugin::Sender.send_message("http://localhost/contact", 'http//profile', @mail)
25 assert_equal ['john@example.com'], response.to 27 assert_equal ['john@example.com'], response.to
26 end 28 end
plugins/send_email/test/unit/send_email_plugin_test.rb
@@ -26,4 +26,12 @@ class SendEmailPluginTest &lt; ActiveSupport::TestCase @@ -26,4 +26,12 @@ class SendEmailPluginTest &lt; ActiveSupport::TestCase
26 assert_match /profile\/#{@plugin.context.profile.identifier}\/plugin\/send_email\/deliver/, @plugin.parse_content("expand this macro {sendemail}", nil).first 26 assert_match /profile\/#{@plugin.context.profile.identifier}\/plugin\/send_email\/deliver/, @plugin.parse_content("expand this macro {sendemail}", nil).first
27 end 27 end
28 28
  29 + should 'expand macro used on form on profile context' do
  30 + profile = fast_create(Community)
  31 + @plugin.context.stubs(:profile).returns(profile)
  32 + article = RawHTMLArticle.create!(:name => 'Raw HTML', :body => "<form action='{sendemail}'></form>", :profile => profile)
  33 +
  34 + assert_match /profile\/#{profile.identifier}\/plugin\/send_email\/deliver/, @plugin.parse_content(article.to_html, nil).first
  35 + end
  36 +
29 end 37 end
plugins/send_email/views/send_email_plugin/sender/message.html.erb
@@ -1,8 +0,0 @@ @@ -1,8 +0,0 @@
1 -<%= _('Contact from %s') % @referer %>  
2 -  
3 -<%= word_wrap(@message || @mail.message) %>  
4 -<% (@params || @mail.params).each_pair do |key, value| %>  
5 -<%= key %>: <%= word_wrap(value) %>  
6 -<% end %>  
7 ----  
8 -<%= url_for @context_url %>  
plugins/send_email/views/send_email_plugin/sender/send_message.html.erb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +<%= _('Contact from %s') % @referer %>
  2 +
  3 +<%= word_wrap(@message || @mail.message) %>
  4 +
  5 +<% (@params || @mail.params).each_pair do |key, value| %>
  6 +<%= key %>: <%= word_wrap(value) %>
  7 +<% end %>
  8 +---
  9 +<%= url_for @context_url %>
plugins/send_email/views/send_email_plugin/success.html.erb
@@ -2,7 +2,7 @@ @@ -2,7 +2,7 @@
2 2
3 <table class='sendemail-plugin-message-sent'> 3 <table class='sendemail-plugin-message-sent'>
4 <tr><td class='label'><strong><%= c_('Subject') %>:</strong></td><td class='value'><em><%=h @mail.subject %></em></td></tr> 4 <tr><td class='label'><strong><%= c_('Subject') %>:</strong></td><td class='value'><em><%=h @mail.subject %></em></td></tr>
5 - <tr><td class='label'><strong><%= c_('Message') %>:</strong></td><td class='value'><pre><%=h render :file => 'send_email_plugin/sender/message' %></pre></td></tr> 5 + <tr><td class='label'><strong><%= c_('Message') %>:</strong></td><td class='value'><pre><%=h render :file => 'send_email_plugin/sender/send_message' %></pre></td></tr>
6 </table> 6 </table>
7 7
8 <p><%= button :back, c_('Back'), :back %></p> 8 <p><%= button :back, c_('Back'), :back %></p>
plugins/sub_organizations/db/migrate/20150508153119_add_timestamp_to_relation.rb 0 → 100644
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 +class AddTimestampToRelation < ActiveRecord::Migration
  2 + def change
  3 + add_column :sub_organizations_plugin_relations, :created_at, :datetime
  4 + add_column :sub_organizations_plugin_relations, :updated_at, :datetime
  5 + end
  6 +end
plugins/sub_organizations/lib/sub_organizations_plugin/relation.rb
1 class SubOrganizationsPlugin::Relation < Noosfero::Plugin::ActiveRecord 1 class SubOrganizationsPlugin::Relation < Noosfero::Plugin::ActiveRecord
2 - record_timestamps = false  
3 -  
4 belongs_to :parent, :polymorphic => true 2 belongs_to :parent, :polymorphic => true
5 belongs_to :child, :polymorphic => true 3 belongs_to :child, :polymorphic => true
6 4
plugins/vote/public/style.css
1 .vote-actions { 1 .vote-actions {
2 - position: absolute;  
3 top: 40px; 2 top: 40px;
4 right: 0px; 3 right: 0px;
5 } 4 }
plugins/vote/views/vote/_vote.html.erb
@@ -5,7 +5,7 @@ reload_url = url_for(:controller =&gt; &#39;vote_plugin_profile&#39;, :profile =&gt; profile.i @@ -5,7 +5,7 @@ reload_url = url_for(:controller =&gt; &#39;vote_plugin_profile&#39;, :profile =&gt; profile.i
5 5
6 <span id="vote_<%= model %>_<%= target.id %>_<%= vote %>" data-reload_url=<%= reload_url %> class="vote-action action <%= action %>-action"> 6 <span id="vote_<%= model %>_<%= target.id %>_<%= vote %>" data-reload_url=<%= reload_url %> class="vote-action action <%= action %>-action">
7 7
8 - <%= link_to_remote content_tag(:span, count, :class=>'like-action-counter') + content_tag(:span, '', :class=>"action-icon #{action}"), :url => url, :html => {:class => "#{active ? 'like-action-active':''} #{user ? '':'disabled'}"} %> 8 + <%= link_to content_tag(:span, count, :class=>'like-action-counter') + content_tag(:span, '', :class=>"action-icon #{action}"), url, :class => "#{active ? 'like-action-active':''} #{user ? '':'disabled'} require-login-popup" %>
9 9
10 <% if !voters.blank? %> 10 <% if !voters.blank? %>
11 <span class="vote-detail"> 11 <span class="vote-detail">
public/designs/templates/lefttopright/config.yml 0 → 100644
@@ -0,0 +1,4 @@ @@ -0,0 +1,4 @@
  1 +name: "Top and Side Bars"
  2 +title: "1 max colum at left, 1 min colum at right, 1 top line"
  3 +description: "A template with 1 colum in left, 1 colum in right and 1 line in top"
  4 +number_of_boxes: 4
public/designs/templates/lefttopright/javascripts/template.js 0 → 100644
@@ -0,0 +1,6 @@ @@ -0,0 +1,6 @@
  1 +$(document).ready(function() {
  2 + var box_4_height = $(".box-4").height();
  3 +
  4 + // Make box-2(the most left one) stay align with box-4
  5 + $(".box-2").css("margin-top", "-"+box_4_height+"px");
  6 +});
public/designs/templates/lefttopright/stylesheets/style.css 0 → 100644
@@ -0,0 +1,42 @@ @@ -0,0 +1,42 @@
  1 +#boxes {
  2 + display: table;
  3 + width: 100%;
  4 +}
  5 +
  6 +.box-1 {
  7 + width: 58%;
  8 + float: left;
  9 + margin: 1% 1% 0% 1%;
  10 +}
  11 +
  12 +
  13 +.box-2 {
  14 + position: relative;
  15 + float: left;
  16 + width: 20%;
  17 +}
  18 +
  19 +.box-3 {
  20 + position: relative;
  21 + float: right;
  22 + width: 20%;
  23 + margin-top: 1%;
  24 +}
  25 +
  26 +.box-4 {
  27 + float: left;
  28 + width: 79%;
  29 + margin-left: 21%;
  30 +}
  31 +
  32 +#profile-activity ul,
  33 +#profile-network ul,
  34 +#profile-wall ul {
  35 + width: 460px;
  36 +}
  37 +#profile-activity ul.comment-replies,
  38 +#profile-network ul.comment-replies,
  39 +#profile-wall ul.comment-replies {
  40 + width: auto;
  41 +}
  42 +
public/designs/templates/lefttopright/thumbnail.png 0 → 100644

3.02 KB

public/designs/templates/lefttopright/thumbnail.svg 0 → 100644
@@ -0,0 +1,434 @@ @@ -0,0 +1,434 @@
  1 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
  2 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
  3 +
  4 +<svg
  5 + xmlns:dc="http://purl.org/dc/elements/1.1/"
  6 + xmlns:cc="http://creativecommons.org/ns#"
  7 + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  8 + xmlns:svg="http://www.w3.org/2000/svg"
  9 + xmlns="http://www.w3.org/2000/svg"
  10 + xmlns:xlink="http://www.w3.org/1999/xlink"
  11 + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
  12 + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
  13 + width="64px"
  14 + height="64px"
  15 + id="svg2383"
  16 + sodipodi:version="0.32"
  17 + inkscape:version="0.48.3.1 r9886"
  18 + sodipodi:docname="thumbnail.svg"
  19 + inkscape:output_extension="org.inkscape.output.svg.inkscape"
  20 + inkscape:export-filename="thumbnail.png"
  21 + inkscape:export-xdpi="90"
  22 + inkscape:export-ydpi="90"
  23 + version="1.1">
  24 + <defs
  25 + id="defs2385">
  26 + <linearGradient
  27 + id="linearGradient3263">
  28 + <stop
  29 + id="stop3265"
  30 + offset="0"
  31 + style="stop-color:#204a87;stop-opacity:1" />
  32 + <stop
  33 + id="stop3267"
  34 + offset="1"
  35 + style="stop-color:#729fcf;stop-opacity:1" />
  36 + </linearGradient>
  37 + <linearGradient
  38 + id="linearGradient3257"
  39 + inkscape:collect="always">
  40 + <stop
  41 + id="stop3259"
  42 + offset="0"
  43 + style="stop-color:#204a87;stop-opacity:1" />
  44 + <stop
  45 + id="stop3261"
  46 + offset="1"
  47 + style="stop-color:#729fcf;stop-opacity:1" />
  48 + </linearGradient>
  49 + <linearGradient
  50 + inkscape:collect="always"
  51 + id="linearGradient3245">
  52 + <stop
  53 + style="stop-color:#204a87;stop-opacity:1"
  54 + offset="0"
  55 + id="stop3247" />
  56 + <stop
  57 + style="stop-color:#729fcf;stop-opacity:1"
  58 + offset="1"
  59 + id="stop3249" />
  60 + </linearGradient>
  61 + <inkscape:perspective
  62 + sodipodi:type="inkscape:persp3d"
  63 + inkscape:vp_x="0 : 32 : 1"
  64 + inkscape:vp_y="0 : 1000 : 0"
  65 + inkscape:vp_z="64 : 32 : 1"
  66 + inkscape:persp3d-origin="32 : 21.333333 : 1"
  67 + id="perspective2391" />
  68 + <filter
  69 + inkscape:collect="always"
  70 + id="filter3241">
  71 + <feGaussianBlur
  72 + inkscape:collect="always"
  73 + stdDeviation="0.9075"
  74 + id="feGaussianBlur3243" />
  75 + </filter>
  76 + <linearGradient
  77 + inkscape:collect="always"
  78 + xlink:href="#linearGradient3245"
  79 + id="linearGradient3251"
  80 + x1="11.5"
  81 + y1="60.5"
  82 + x2="3.5"
  83 + y2="3.5"
  84 + gradientUnits="userSpaceOnUse"
  85 + gradientTransform="translate(2,0)" />
  86 + <linearGradient
  87 + inkscape:collect="always"
  88 + xlink:href="#linearGradient3263"
  89 + id="linearGradient3253"
  90 + x1="49.5"
  91 + y1="60.5"
  92 + x2="23.5"
  93 + y2="3.5"
  94 + gradientUnits="userSpaceOnUse"
  95 + gradientTransform="translate(2,0)" />
  96 + <linearGradient
  97 + inkscape:collect="always"
  98 + xlink:href="#linearGradient3257"
  99 + id="linearGradient3255"
  100 + x1="60.5"
  101 + y1="60.5"
  102 + x2="51.5"
  103 + y2="3.5"
  104 + gradientUnits="userSpaceOnUse" />
  105 + <filter
  106 + color-interpolation-filters="sRGB"
  107 + inkscape:collect="always"
  108 + id="filter3241-2">
  109 + <feGaussianBlur
  110 + inkscape:collect="always"
  111 + stdDeviation="0.9075"
  112 + id="feGaussianBlur3243-4" />
  113 + </filter>
  114 + <linearGradient
  115 + inkscape:collect="always"
  116 + xlink:href="#linearGradient3245-1"
  117 + id="linearGradient3251-0"
  118 + x1="11.5"
  119 + y1="60.5"
  120 + x2="3.5"
  121 + y2="3.5"
  122 + gradientUnits="userSpaceOnUse"
  123 + gradientTransform="translate(249.71429,298.93361)" />
  124 + <linearGradient
  125 + inkscape:collect="always"
  126 + id="linearGradient3245-1">
  127 + <stop
  128 + style="stop-color:#204a87;stop-opacity:1"
  129 + offset="0"
  130 + id="stop3247-6" />
  131 + <stop
  132 + style="stop-color:#729fcf;stop-opacity:1"
  133 + offset="1"
  134 + id="stop3249-5" />
  135 + </linearGradient>
  136 + <filter
  137 + color-interpolation-filters="sRGB"
  138 + inkscape:collect="always"
  139 + id="filter3241-4-8">
  140 + <feGaussianBlur
  141 + inkscape:collect="always"
  142 + stdDeviation="0.9075"
  143 + id="feGaussianBlur3243-0-7" />
  144 + </filter>
  145 + <linearGradient
  146 + inkscape:collect="always"
  147 + xlink:href="#linearGradient3263-5-8"
  148 + id="linearGradient5185"
  149 + gradientUnits="userSpaceOnUse"
  150 + gradientTransform="matrix(1.4160224,0,0,0.76166072,243.22589,313.33388)"
  151 + x1="42.5"
  152 + y1="60.5"
  153 + x2="19.5"
  154 + y2="3.5" />
  155 + <linearGradient
  156 + id="linearGradient3263-5-8">
  157 + <stop
  158 + id="stop3265-4-3"
  159 + offset="0"
  160 + style="stop-color:#204a87;stop-opacity:1" />
  161 + <stop
  162 + id="stop3267-2-4"
  163 + offset="1"
  164 + style="stop-color:#729fcf;stop-opacity:1" />
  165 + </linearGradient>
  166 + <filter
  167 + color-interpolation-filters="sRGB"
  168 + inkscape:collect="always"
  169 + id="filter3241-0">
  170 + <feGaussianBlur
  171 + inkscape:collect="always"
  172 + stdDeviation="0.9075"
  173 + id="feGaussianBlur3243-3" />
  174 + </filter>
  175 + <linearGradient
  176 + inkscape:collect="always"
  177 + xlink:href="#linearGradient3245-7"
  178 + id="linearGradient5168"
  179 + gradientUnits="userSpaceOnUse"
  180 + gradientTransform="matrix(1.0025263,0,0,0.76423683,344.68831,300.13218)"
  181 + x1="11.5"
  182 + y1="60.5"
  183 + x2="3.5"
  184 + y2="3.5" />
  185 + <linearGradient
  186 + inkscape:collect="always"
  187 + id="linearGradient3245-7">
  188 + <stop
  189 + style="stop-color:#204a87;stop-opacity:1"
  190 + offset="0"
  191 + id="stop3247-0" />
  192 + <stop
  193 + style="stop-color:#729fcf;stop-opacity:1"
  194 + offset="1"
  195 + id="stop3249-7" />
  196 + </linearGradient>
  197 + <linearGradient
  198 + inkscape:collect="always"
  199 + xlink:href="#linearGradient3245-70"
  200 + id="linearGradient3251-55"
  201 + x1="11.5"
  202 + y1="60.5"
  203 + x2="3.5"
  204 + y2="3.5"
  205 + gradientUnits="userSpaceOnUse"
  206 + gradientTransform="matrix(1.0025263,0,0,0.76423683,344.68831,300.13218)" />
  207 + <linearGradient
  208 + inkscape:collect="always"
  209 + id="linearGradient3245-70">
  210 + <stop
  211 + style="stop-color:#204a87;stop-opacity:1"
  212 + offset="0"
  213 + id="stop3247-2" />
  214 + <stop
  215 + style="stop-color:#729fcf;stop-opacity:1"
  216 + offset="1"
  217 + id="stop3249-87" />
  218 + </linearGradient>
  219 + <linearGradient
  220 + inkscape:collect="always"
  221 + xlink:href="#linearGradient3245-1"
  222 + id="linearGradient5832"
  223 + gradientUnits="userSpaceOnUse"
  224 + gradientTransform="translate(249.71429,298.93361)"
  225 + x1="11.5"
  226 + y1="60.5"
  227 + x2="3.5"
  228 + y2="3.5" />
  229 + <linearGradient
  230 + inkscape:collect="always"
  231 + xlink:href="#linearGradient3263-5-8"
  232 + id="linearGradient5834"
  233 + gradientUnits="userSpaceOnUse"
  234 + gradientTransform="matrix(1.4160224,0,0,0.76166072,243.22589,313.33388)"
  235 + x1="42.5"
  236 + y1="60.5"
  237 + x2="19.5"
  238 + y2="3.5" />
  239 + <linearGradient
  240 + inkscape:collect="always"
  241 + xlink:href="#linearGradient3245-7"
  242 + id="linearGradient5836"
  243 + gradientUnits="userSpaceOnUse"
  244 + gradientTransform="matrix(1.0025263,0,0,0.76423683,344.68831,300.13218)"
  245 + x1="11.5"
  246 + y1="60.5"
  247 + x2="3.5"
  248 + y2="3.5" />
  249 + <linearGradient
  250 + inkscape:collect="always"
  251 + xlink:href="#linearGradient3245-70"
  252 + id="linearGradient5838"
  253 + gradientUnits="userSpaceOnUse"
  254 + gradientTransform="matrix(1.0025263,0,0,0.76423683,344.68831,300.13218)"
  255 + x1="11.5"
  256 + y1="60.5"
  257 + x2="3.5"
  258 + y2="3.5" />
  259 + </defs>
  260 + <sodipodi:namedview
  261 + id="base"
  262 + pagecolor="#ffffff"
  263 + bordercolor="#666666"
  264 + borderopacity="1.0"
  265 + inkscape:pageopacity="0.0"
  266 + inkscape:pageshadow="2"
  267 + inkscape:zoom="2.5351563"
  268 + inkscape:cx="-16.066434"
  269 + inkscape:cy="0.12147739"
  270 + inkscape:current-layer="layer1"
  271 + showgrid="true"
  272 + inkscape:document-units="px"
  273 + inkscape:grid-bbox="true"
  274 + inkscape:window-width="1364"
  275 + inkscape:window-height="678"
  276 + inkscape:window-x="0"
  277 + inkscape:window-y="27"
  278 + objecttolerance="10"
  279 + gridtolerance="10"
  280 + guidetolerance="10"
  281 + inkscape:window-maximized="0">
  282 + <inkscape:grid
  283 + type="xygrid"
  284 + id="grid2382"
  285 + visible="true"
  286 + enabled="true"
  287 + originx="0.5px"
  288 + originy="0.5px"
  289 + empcolor="#0000ff"
  290 + empopacity="0.1254902"
  291 + dotted="true" />
  292 + </sodipodi:namedview>
  293 + <metadata
  294 + id="metadata2388">
  295 + <rdf:RDF>
  296 + <cc:Work
  297 + rdf:about="">
  298 + <dc:format>image/svg+xml</dc:format>
  299 + <dc:type
  300 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
  301 + </cc:Work>
  302 + </rdf:RDF>
  303 + </metadata>
  304 + <g
  305 + id="layer1"
  306 + inkscape:label="Layer 1"
  307 + inkscape:groupmode="layer">
  308 + <g
  309 + transform="translate(-247.62879,-298.93361)"
  310 + id="g5187">
  311 + <g
  312 + id="g4846">
  313 + <g
  314 + id="g3190-2"
  315 + style="opacity:0.4;filter:url(#filter3241-2)"
  316 + transform="translate(250.71429,299.93361)">
  317 + <rect
  318 + y="1.5"
  319 + x="1.5"
  320 + height="59"
  321 + width="11"
  322 + id="rect3184-1"
  323 + style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
  324 + ry="2"
  325 + rx="2" />
  326 + </g>
  327 + <rect
  328 + y="300.43362"
  329 + x="251.21428"
  330 + height="59"
  331 + width="11"
  332 + id="rect2395-8"
  333 + style="fill:url(#linearGradient5832);fill-opacity:1;fill-rule:nonzero;stroke:#204a87;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
  334 + ry="2"
  335 + rx="2" />
  336 + <rect
  337 + ry="1"
  338 + style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
  339 + id="rect3158-7"
  340 + width="9"
  341 + height="57"
  342 + x="252.21428"
  343 + y="301.43362"
  344 + rx="1" />
  345 + </g>
  346 + <g
  347 + transform="matrix(0.69260722,0,0,1,81.51265,0)"
  348 + id="g5180">
  349 + <rect
  350 + rx="2"
  351 + ry="2"
  352 + style="opacity:0.4;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter3241-4-8);enable-background:accumulate"
  353 + id="rect3188-8"
  354 + width="31"
  355 + height="59"
  356 + x="16.5"
  357 + y="2.5"
  358 + transform="matrix(1.4160224,0,0,0.76166071,243.80989,314.09132)" />
  359 + <rect
  360 + y="314.47638"
  361 + x="265.17426"
  362 + height="44.937984"
  363 + width="43.896694"
  364 + id="rect3156-3"
  365 + style="fill:url(#linearGradient5834);fill-opacity:1;fill-rule:nonzero;stroke:#204a87;stroke-width:1.03852236;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
  366 + ry="1.5233214" />
  367 + <rect
  368 + y="315.23804"
  369 + x="266.59027"
  370 + height="43.414661"
  371 + width="41.064651"
  372 + id="rect3162-1"
  373 + style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:1.03852236;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
  374 + ry="0.7616607"
  375 + inkscape:export-xdpi="90"
  376 + inkscape:export-ydpi="90" />
  377 + </g>
  378 + <g
  379 + transform="matrix(0.9761091,0,0,1,6.3333026,0)"
  380 + id="g5108">
  381 + <rect
  382 + rx="2"
  383 + ry="2"
  384 + style="opacity:0.4;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;filter:url(#filter3241-0);enable-background:accumulate"
  385 + id="rect3184-5"
  386 + width="11"
  387 + height="59"
  388 + x="2.5"
  389 + y="2.5"
  390 + transform="matrix(0,1.0025263,-0.76423683,0,312.09322,298.92289)" />
  391 + <g
  392 + transform="matrix(0,1,-1,0,611.46116,-45.820829)"
  393 + id="g4877-9">
  394 + <rect
  395 + ry="1.5284736"
  396 + style="fill:url(#linearGradient5836);fill-opacity:1;fill-rule:nonzero;stroke:#204a87;stroke-width:0.87531;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
  397 + id="rect2395-95"
  398 + width="11.02779"
  399 + height="45.089973"
  400 + x="346.19211"
  401 + y="301.27853" />
  402 + <rect
  403 + y="302.04276"
  404 + x="347.19461"
  405 + height="43.561501"
  406 + width="9.0227375"
  407 + id="rect3158-2"
  408 + style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:0.87531;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
  409 + ry="0.76423681" />
  410 + </g>
  411 + </g>
  412 + <g
  413 + id="g4877-8"
  414 + transform="translate(-47.956003,13.002947)">
  415 + <rect
  416 + y="301.27853"
  417 + x="346.19211"
  418 + height="45.089973"
  419 + width="11.02779"
  420 + id="rect2395-1"
  421 + style="fill:url(#linearGradient5838);fill-opacity:1;fill-rule:nonzero;stroke:#204a87;stroke-width:0.87531;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
  422 + ry="1.5284736" />
  423 + <rect
  424 + ry="0.76423681"
  425 + style="opacity:0.6;fill:none;stroke:#ffffff;stroke-width:0.87531;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;marker:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate"
  426 + id="rect3158-71"
  427 + width="9.0227375"
  428 + height="43.561501"
  429 + x="347.19461"
  430 + y="302.04276" />
  431 + </g>
  432 + </g>
  433 + </g>
  434 +</svg>
public/designs/templates/topleft/stylesheets/style.css
@@ -20,7 +20,7 @@ @@ -20,7 +20,7 @@
20 20
21 .box-3 { 21 .box-3 {
22 position: relative; 22 position: relative;
23 - display: table-footer-group; 23 + display: table-header-group;
24 width: 100%; 24 width: 100%;
25 } 25 }
26 26
public/images/blocks/4.png 0 → 100644

1.14 KB

public/images/blocks/4.svg 0 → 100644
@@ -0,0 +1,83 @@ @@ -0,0 +1,83 @@
  1 +<?xml version="1.0" encoding="UTF-8" standalone="no"?>
  2 +<!-- Created with Inkscape (http://www.inkscape.org/) -->
  3 +
  4 +<svg
  5 + xmlns:dc="http://purl.org/dc/elements/1.1/"
  6 + xmlns:cc="http://creativecommons.org/ns#"
  7 + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
  8 + xmlns:svg="http://www.w3.org/2000/svg"
  9 + xmlns="http://www.w3.org/2000/svg"
  10 + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
  11 + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
  12 + width="64"
  13 + height="64"
  14 + id="svg2"
  15 + sodipodi:version="0.32"
  16 + inkscape:version="0.48.3.1 r9886"
  17 + version="1.0"
  18 + sodipodi:docname="4.svg"
  19 + inkscape:output_extension="org.inkscape.output.svg.inkscape"
  20 + inkscape:export-filename="/home/noosfero/sites/noosfero/public/images/blocks/4.png"
  21 + inkscape:export-xdpi="87.968124"
  22 + inkscape:export-ydpi="87.968124">
  23 + <defs
  24 + id="defs4" />
  25 + <sodipodi:namedview
  26 + id="base"
  27 + pagecolor="#ffffff"
  28 + bordercolor="#666666"
  29 + borderopacity="1.0"
  30 + inkscape:pageopacity="0.0"
  31 + inkscape:pageshadow="2"
  32 + inkscape:zoom="5.921875"
  33 + inkscape:cx="32"
  34 + inkscape:cy="32"
  35 + inkscape:document-units="px"
  36 + inkscape:current-layer="layer1"
  37 + width="64px"
  38 + height="64px"
  39 + inkscape:window-width="1366"
  40 + inkscape:window-height="681"
  41 + inkscape:window-x="0"
  42 + inkscape:window-y="27"
  43 + showgrid="false"
  44 + inkscape:window-maximized="1" />
  45 + <metadata
  46 + id="metadata7">
  47 + <rdf:RDF>
  48 + <cc:Work
  49 + rdf:about="">
  50 + <dc:format>image/svg+xml</dc:format>
  51 + <dc:type
  52 + rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
  53 + <dc:title></dc:title>
  54 + </cc:Work>
  55 + </rdf:RDF>
  56 + </metadata>
  57 + <g
  58 + inkscape:label="Camada 1"
  59 + inkscape:groupmode="layer"
  60 + id="layer1">
  61 + <path
  62 + sodipodi:type="arc"
  63 + style="fill:#000000;fill-opacity:0;stroke:#000000;stroke-width:4.5;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:0.19607843"
  64 + id="path2162"
  65 + sodipodi:cx="24.12665"
  66 + sodipodi:cy="24.063324"
  67 + sodipodi:rx="21.593668"
  68 + sodipodi:ry="21.277044"
  69 + d="M 45.720318 24.063324 A 21.593668 21.277044 0 1 1 2.5329819,24.063324 A 21.593668 21.277044 0 1 1 45.720318 24.063324 z"
  70 + transform="translate(7.8733501,7.936676)" />
  71 + <text
  72 + xml:space="preserve"
  73 + style="font-size:42.00993729px;font-style:normal;font-variant:normal;font-weight:bold;font-stretch:normal;text-align:start;line-height:125%;writing-mode:lr-tb;text-anchor:start;fill:#000000;fill-opacity:0.19607843;stroke:none;font-family:FreeSans"
  74 + x="16.267668"
  75 + y="47.399117"
  76 + id="text3134"
  77 + sodipodi:linespacing="125%"><tspan
  78 + sodipodi:role="line"
  79 + id="tspan3136"
  80 + x="16.267668"
  81 + y="47.399117">4</tspan></text>
  82 + </g>
  83 +</svg>
public/images/control-panel/role-management.gif 0 → 100644

2.07 KB

public/images/control-panel/role-management.png 0 → 100644

3.63 KB

public/javascripts/application.js
@@ -27,6 +27,7 @@ @@ -27,6 +27,7 @@
27 *= require manage-products.js 27 *= require manage-products.js
28 *= require catalog.js 28 *= require catalog.js
29 *= require autogrow.js 29 *= require autogrow.js
  30 +*= require require_login.js
30 */ 31 */
31 32
32 // scope for noosfero stuff 33 // scope for noosfero stuff
public/javascripts/assign_role.js 0 → 100644
@@ -0,0 +1,19 @@ @@ -0,0 +1,19 @@
  1 +(function($){
  2 + 'use strict';
  3 +
  4 + function toggle_assignment_method() {
  5 + if (this.value != "roles") {
  6 + $('.assign_by_roles').hide();
  7 + $('.assign_by_members').show();
  8 + } else {
  9 + $('.assign_by_members').hide();
  10 + $('.assign_by_roles').show();
  11 + }
  12 + }
  13 +
  14 + $(document).ready(function() {
  15 + $('.assign_by_roles').hide();
  16 + // Event triggers
  17 + $('.assign_role_by').click(toggle_assignment_method);
  18 + });
  19 +})(jQuery);
public/javascripts/manage-fields.js
@@ -57,7 +57,7 @@ jQuery(document).ready(function(){ @@ -57,7 +57,7 @@ jQuery(document).ready(function(){
57 } 57 }
58 58
59 var checkbox = jQuery(checkboxes[i+3]).attr("id").split("_") 59 var checkbox = jQuery(checkboxes[i+3]).attr("id").split("_")
60 - jQuery("#" + checkbox.first() + "_" + checkbox.last()).attr("checked", allchecked) 60 + jQuery("#" + checkbox[0] + "_" + checkbox[checkbox.length-1]).attr("checked", allchecked)
61 } 61 }
62 } 62 }
63 63
@@ -74,10 +74,10 @@ jQuery(document).ready(function(){ @@ -74,10 +74,10 @@ jQuery(document).ready(function(){
74 74
75 jQuery("input[type='checkbox']").click(function (){ 75 jQuery("input[type='checkbox']").click(function (){
76 var checkbox = jQuery(this).attr("id").split("_") 76 var checkbox = jQuery(this).attr("id").split("_")
77 - verify_checked(checkbox.first()) 77 + verify_checked(checkbox[0])
78 78
79 if(this.checked == false) { 79 if(this.checked == false) {
80 - jQuery("#" + checkbox.first() + "_" + checkbox.last()).attr("checked", false) 80 + jQuery("#" + checkbox[0] + "_" + checkbox[checkbox.length-1]).attr("checked", false)
81 } 81 }
82 }) 82 })
83 }) 83 })
public/javascripts/report-abuse.js
1 jQuery(function($) { 1 jQuery(function($) {
2 $('.report-abuse-action').live('click', function() { 2 $('.report-abuse-action').live('click', function() {
3 - if($(this).attr('href')){  
4 - noosfero.modal.inline($(this).attr('href'), {  
5 - innerHeight: '300px',  
6 - innerWidth: '445px'  
7 - });  
8 - } 3 + if($(this).attr('href'))
  4 + noosfero.modal.url($(this).attr('href'));
  5 +
9 return false; 6 return false;
10 }); 7 });
11 8
public/javascripts/require_login.js 0 → 100644
@@ -0,0 +1,25 @@ @@ -0,0 +1,25 @@
  1 +(function($) {
  2 + $(window).bind('userDataLoaded', function(event, data) {
  3 + $(".require-login-popup").live('click', function(){
  4 + clicked = $(this);
  5 + url = clicked.attr("href");
  6 + if(url!=undefined && url!='' && url!='#') {
  7 + if(!data.login) {
  8 + url = $.param.querystring(url, "require_login_popup=true");
  9 + }
  10 + loading_for_button(this);
  11 + $.post(url, function(data){
  12 + if(data.require_login_popup) {
  13 + $('#link_login').click(); //TODO see a better way to show login popup
  14 + }
  15 + }).complete(function() {
  16 + clicked.css("cursor","");
  17 + $(".small-loading").remove();
  18 + });
  19 + } else {
  20 + $('#link_login').click();
  21 + }
  22 + return false;
  23 + });
  24 + });
  25 +})(jQuery);
public/stylesheets/application.css
@@ -1501,6 +1501,14 @@ a.comment-picture { @@ -1501,6 +1501,14 @@ a.comment-picture {
1501 #content .title { 1501 #content .title {
1502 margin-bottom: 2px; 1502 margin-bottom: 2px;
1503 } 1503 }
  1504 +.blog-post .post-pic {
  1505 + background-position: 50% 40%;
  1506 + background-size: cover;
  1507 + height: 150px;
  1508 +}
  1509 +.blog-post .post-pic.empty {
  1510 + display: none;
  1511 +}
1504 .metadata, .blog-post .metadata { 1512 .metadata, .blog-post .metadata {
1505 display: block; 1513 display: block;
1506 text-align: center; 1514 text-align: center;
@@ -1834,6 +1842,9 @@ a.button.disabled, input.disabled { @@ -1834,6 +1842,9 @@ a.button.disabled, input.disabled {
1834 #box-organizer div.box-3 { 1842 #box-organizer div.box-3 {
1835 background-image: url(../images/blocks/3.png); 1843 background-image: url(../images/blocks/3.png);
1836 } 1844 }
  1845 +#box-organizer div.box-4 {
  1846 + background-image: url(../images/blocks/4.png);
  1847 +}
1837 #box-organizer .block { 1848 #box-organizer .block {
1838 cursor: move; 1849 cursor: move;
1839 } 1850 }
@@ -4677,6 +4688,12 @@ h1#agenda-title { @@ -4677,6 +4688,12 @@ h1#agenda-title {
4677 .controller-profile_editor a.control-panel-welcome-page { 4688 .controller-profile_editor a.control-panel-welcome-page {
4678 background-image: url(../images/control-panel/welcome-page.png) 4689 background-image: url(../images/control-panel/welcome-page.png)
4679 } 4690 }
  4691 +.controller-profile_editor a.control-panel-roles {
  4692 + background-image: url(../images/control-panel/role-management.png)
  4693 +}
  4694 +.controller-profile_editor .msie6 a.control-panel-roles {
  4695 + background-image: url(../images/control-panel/role-management.gif)
  4696 +}
4680 /* ==> public/stylesheets/controller_profile_members.css <== */ 4697 /* ==> public/stylesheets/controller_profile_members.css <== */
4681 .controller-profile_members .no-boxes { 4698 .controller-profile_members .no-boxes {
4682 margin: 30px 4699 margin: 30px
script/install-dependencies/debian-wheezy.sh
1 -binary_packages='deb http://download.noosfero.org/debian/wheezy-1.1 ./' 1 +binary_packages='deb http://download.noosfero.org/debian/wheezy-1.2 ./'
2 2
3 source_packages=$(echo "$binary_packages" | sed -e 's/^deb/deb-src/') 3 source_packages=$(echo "$binary_packages" | sed -e 's/^deb/deb-src/')
4 4
@@ -53,6 +53,13 @@ FPQAoNmiMgP6zGF9rgOEWMEiFEryayrz @@ -53,6 +53,13 @@ FPQAoNmiMgP6zGF9rgOEWMEiFEryayrz
53 EOF 53 EOF
54 fi 54 fi
55 55
  56 +if grep -qrl wheezy /etc/apt/sources.list* && ! grep -qrl wheezy-backports /etc/apt/sources.list*; then
  57 + sudo tee /etc/apt/sources.list.d/backports.list <<EOF
  58 +deb http://httpredir.debian.org/debian wheezy-backports main
  59 +EOF
  60 +fi
  61 +
  62 +
56 if test -f tmp/debian/Release.gpg; then 63 if test -f tmp/debian/Release.gpg; then
57 echo "deb file://$(pwd)/tmp/debian/ ./" | sudo tee /etc/apt/sources.list.d/local.list 64 echo "deb file://$(pwd)/tmp/debian/ ./" | sudo tee /etc/apt/sources.list.d/local.list
58 sudo apt-key add tmp/debian/signing-key.asc 65 sudo apt-key add tmp/debian/signing-key.asc
@@ -65,6 +72,9 @@ run sudo apt-get -qy dist-upgrade @@ -65,6 +72,9 @@ run sudo apt-get -qy dist-upgrade
65 72
66 run sudo apt-get -y install dctrl-tools 73 run sudo apt-get -y install dctrl-tools
67 74
  75 +# *sigh* need ruby-rspec from backports
  76 +run sudo apt-get -y install -t wheezy-backports ruby-rspec
  77 +
68 # needed to run noosfero 78 # needed to run noosfero
69 packages=$(grep-dctrl -n -s Build-Depends,Depends,Recommends -S -X noosfero debian/control | sed -e '/^\s*#/d; s/([^)]*)//g; s/,\s*/\n/g' | grep -v 'memcached\|debconf\|dbconfig-common\|misc:Depends\|adduser\|mail-transport-agent') 79 packages=$(grep-dctrl -n -s Build-Depends,Depends,Recommends -S -X noosfero debian/control | sed -e '/^\s*#/d; s/([^)]*)//g; s/,\s*/\n/g' | grep -v 'memcached\|debconf\|dbconfig-common\|misc:Depends\|adduser\|mail-transport-agent')
70 run sudo apt-get -y install $packages 80 run sudo apt-get -y install $packages
script/production
@@ -85,7 +85,7 @@ environments_loop() { @@ -85,7 +85,7 @@ environments_loop() {
85 } 85 }
86 86
87 do_running() { 87 do_running() {
88 - pids=$(sed "s/.*/& /" tmp/pids/thin.*.pid | tr -d '\n' 2>/dev/null || true) 88 + pids=$(sed "s/.*/& /" tmp/pids/thin.*.pid 2>/dev/null | tr -d '\n')
89 # passes if any of $pids exist, fails otherwise 89 # passes if any of $pids exist, fails otherwise
90 kill -0 $pids > /dev/null 2>&1 90 kill -0 $pids > /dev/null 2>&1
91 } 91 }
test/factories.rb
@@ -454,7 +454,7 @@ module Noosfero::Factory @@ -454,7 +454,7 @@ module Noosfero::Factory
454 end 454 end
455 455
456 def defaults_for_suggest_article 456 def defaults_for_suggest_article
457 - { :name => 'Sender', :email => 'sender@example.com', :article_name => 'Some title', :article_body => 'some body text', :article_abstract => 'some abstract text'} 457 + { :name => 'Sender', :email => 'sender@example.com', :article => {:name => 'Some title', :body => 'some body text', :abstract => 'some abstract text'}}
458 end 458 end
459 459
460 def defaults_for_comment(params = {}) 460 def defaults_for_comment(params = {})
test/functional/application_controller_test.rb
@@ -578,4 +578,22 @@ class ApplicationControllerTest &lt; ActionController::TestCase @@ -578,4 +578,22 @@ class ApplicationControllerTest &lt; ActionController::TestCase
578 assert_response :success 578 assert_response :success
579 end 579 end
580 580
  581 + should "redirect to 404 if profile is '~' and user is not logged in" do
  582 + get :index, :profile => '~'
  583 + assert_response :missing
  584 + end
  585 +
  586 + should "redirect to action when profile is '~' " do
  587 + login_as('ze')
  588 + get :index, :profile => '~'
  589 + assert_response 302
  590 + end
  591 +
  592 + should "substitute '~' by current user and redirect properly " do
  593 + login_as('ze')
  594 + profile = Profile.where(:identifier => 'ze').first
  595 + get :index, :profile => '~'
  596 + assert_redirected_to :controller => 'test', :action => 'index', :profile => profile.identifier
  597 + end
  598 +
581 end 599 end
test/functional/cms_controller_test.rb
@@ -1407,22 +1407,57 @@ class CmsControllerTest &lt; ActionController::TestCase @@ -1407,22 +1407,57 @@ class CmsControllerTest &lt; ActionController::TestCase
1407 assert_template 'suggest_an_article' 1407 assert_template 'suggest_an_article'
1408 end 1408 end
1409 1409
  1410 + should 'display name and email when a not logged in user suggest an article' do
  1411 + logout
  1412 + get :suggest_an_article, :profile => profile.identifier, :back_to => 'action_view'
  1413 +
  1414 + assert_select '#task_name'
  1415 + assert_select '#task_email'
  1416 + end
  1417 +
  1418 + should 'do not display name and email when a logged in user suggest an article' do
  1419 + get :suggest_an_article, :profile => profile.identifier, :back_to => 'action_view'
  1420 +
  1421 + assert_select '#task_name', 0
  1422 + assert_select '#task_email', 0
  1423 + end
  1424 +
  1425 + should 'display captcha when suggest an article for not logged in users' do
  1426 + logout
  1427 + get :suggest_an_article, :profile => profile.identifier, :back_to => 'action_view'
  1428 +
  1429 + assert_select '#dynamic_recaptcha'
  1430 + end
  1431 +
  1432 + should 'not display captcha when suggest an article for logged in users' do
  1433 + get :suggest_an_article, :profile => profile.identifier, :back_to => 'action_view'
  1434 +
  1435 + assert_select '#dynamic_recaptcha', 0
  1436 + end
  1437 +
1410 should 'render TinyMce Editor on suggestion of article' do 1438 should 'render TinyMce Editor on suggestion of article' do
1411 logout 1439 logout
1412 get :suggest_an_article, :profile => profile.identifier 1440 get :suggest_an_article, :profile => profile.identifier
1413 1441
1414 - assert_tag :tag => 'textarea', :attributes => { :name => /article_abstract/, :class => 'mceEditor' }  
1415 - assert_tag :tag => 'textarea', :attributes => { :name => /article_body/, :class => 'mceEditor' } 1442 + assert_tag :tag => 'textarea', :attributes => { :name => /task\[article\]\[abstract\]/, :class => 'mceEditor' }
  1443 + assert_tag :tag => 'textarea', :attributes => { :name => /task\[article\]\[body\]/, :class => 'mceEditor' }
1416 end 1444 end
1417 1445
1418 should 'create a task suggest task to a profile' do 1446 should 'create a task suggest task to a profile' do
1419 c = Community.create!(:name => 'test comm', :identifier => 'test_comm', :moderated_articles => true) 1447 c = Community.create!(:name => 'test comm', :identifier => 'test_comm', :moderated_articles => true)
1420 1448
1421 assert_difference 'SuggestArticle.count' do 1449 assert_difference 'SuggestArticle.count' do
1422 - post :suggest_an_article, :profile => c.identifier, :back_to => 'action_view', :task => {:article_name => 'some name', :article_body => 'some body', :email => 'some@localhost.com', :name => 'some name'} 1450 + post :suggest_an_article, :profile => c.identifier, :back_to => 'action_view', :task => {:article => {:name => 'some name', :body => 'some body'}, :email => 'some@localhost.com', :name => 'some name'}
1423 end 1451 end
1424 end 1452 end
1425 1453
  1454 + should 'create suggest task with logged in user as the article author' do
  1455 + c = Community.create!(:name => 'test comm', :identifier => 'test_comm', :moderated_articles => true)
  1456 +
  1457 + post :suggest_an_article, :profile => c.identifier, :back_to => 'action_view', :task => {:article => {:name => 'some name', :body => 'some body'}}
  1458 + assert_equal profile, SuggestArticle.last.requestor
  1459 + end
  1460 +
1426 should 'suggest an article from a profile' do 1461 should 'suggest an article from a profile' do
1427 c = Community.create!(:name => 'test comm', :identifier => 'test_comm', :moderated_articles => true) 1462 c = Community.create!(:name => 'test comm', :identifier => 'test_comm', :moderated_articles => true)
1428 get :suggest_an_article, :profile => c.identifier, :back_to => c.identifier 1463 get :suggest_an_article, :profile => c.identifier, :back_to => c.identifier
test/functional/content_viewer_controller_test.rb
@@ -175,7 +175,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase @@ -175,7 +175,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
175 admin = fast_create(Person) 175 admin = fast_create(Person)
176 community.add_member(admin) 176 community.add_member(admin)
177 177
178 - folder = fast_create(Folder, :profile_id => community.id, :published => false) 178 + folder = fast_create(Folder, :profile_id => community.id, :published => false, :show_to_followers => false)
179 community.add_member(profile) 179 community.add_member(profile)
180 login_as(profile.identifier) 180 login_as(profile.identifier)
181 181
@@ -278,7 +278,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase @@ -278,7 +278,7 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
278 should 'not give access to private articles if logged in and only member' do 278 should 'not give access to private articles if logged in and only member' do
279 person = create_user('test_user').person 279 person = create_user('test_user').person
280 profile = Profile.create!(:name => 'test profile', :identifier => 'test_profile') 280 profile = Profile.create!(:name => 'test profile', :identifier => 'test_profile')
281 - intranet = Folder.create!(:name => 'my_intranet', :profile => profile, :published => false) 281 + intranet = Folder.create!(:name => 'my_intranet', :profile => profile, :published => false, :show_to_followers => false)
282 profile.affiliate(person, Profile::Roles.member(profile.environment.id)) 282 profile.affiliate(person, Profile::Roles.member(profile.environment.id))
283 login_as('test_user') 283 login_as('test_user')
284 284
@@ -780,6 +780,20 @@ class ContentViewerControllerTest &lt; ActionController::TestCase @@ -780,6 +780,20 @@ class ContentViewerControllerTest &lt; ActionController::TestCase
780 assert_no_tag :tag => 'div', :attributes => { :class => 'short-post'}, :content => /Anything/ 780 assert_no_tag :tag => 'div', :attributes => { :class => 'short-post'}, :content => /Anything/
781 end 781 end
782 782
  783 + should 'show only first paragraph with picture of posts if visualization_format is short+pic' do
  784 + login_as(profile.identifier)
  785 +
  786 + blog = Blog.create!(:name => 'A blog test', :profile => profile, :visualization_format => 'short+pic')
  787 +
  788 + blog.posts << TinyMceArticle.create!(:name => 'first post', :parent => blog, :profile => profile, :body => '<p>Content to be displayed.</p> <img src="pic.jpg">')
  789 +
  790 + get :view_page, :profile => profile.identifier, :page => blog.path
  791 +
  792 + assert_select '.blog-post .post-pic' do |el|
  793 + assert_match /background-image:url\(pic.jpg\)/, el.to_s
  794 + end
  795 + end
  796 +
783 should 'display link to edit blog for allowed' do 797 should 'display link to edit blog for allowed' do
784 blog = fast_create(Blog, :profile_id => profile.id, :path => 'blog') 798 blog = fast_create(Blog, :profile_id => profile.id, :path => 'blog')
785 login_as(profile.identifier) 799 login_as(profile.identifier)
test/functional/profile_design_controller_test.rb
@@ -737,9 +737,9 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase @@ -737,9 +737,9 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase
737 end 737 end
738 end 738 end
739 739
740 - test 'should forbid POST to save for fixed blocks' do 740 + test 'should forbid POST to save for uneditable blocks' do
741 block = profile.blocks.last 741 block = profile.blocks.last
742 - block.fixed = true 742 + block.edit_modes = "none"
743 block.save! 743 block.save!
744 744
745 post :save, id: block.id, profile: profile.identifier 745 post :save, id: block.id, profile: profile.identifier
@@ -748,7 +748,7 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase @@ -748,7 +748,7 @@ class ProfileDesignControllerTest &lt; ActionController::TestCase
748 748
749 test 'should forbid POST to move_block for fixed blocks' do 749 test 'should forbid POST to move_block for fixed blocks' do
750 block = profile.blocks.last 750 block = profile.blocks.last
751 - block.fixed = true 751 + block.move_modes = "none"
752 block.save! 752 block.save!
753 753
754 post :move_block, id: block.id, profile: profile.identifier, target: "end-of-box-#{@box3.id}" 754 post :move_block, id: block.id, profile: profile.identifier, target: "end-of-box-#{@box3.id}"
test/functional/profile_roles_controller_test.rb 0 → 100644
@@ -0,0 +1,106 @@ @@ -0,0 +1,106 @@
  1 +require_relative "../test_helper"
  2 +require 'profile_roles_controller'
  3 +
  4 +class ProfileRolesControllerTest < ActionController::TestCase
  5 +
  6 + def setup
  7 + @controller = ProfileRolesController.new
  8 + @request = ActionController::TestRequest.new
  9 + @response = ActionController::TestResponse.new
  10 + @role = Role.find(:first)
  11 + end
  12 +
  13 + should 'create a custom role' do
  14 + community = fast_create(Community)
  15 + admin = create_user_with_permission('admin_user', 'manage_custom_roles', community)
  16 + login_as :admin_user
  17 + post :create, :profile => community.identifier, :role => {:name => "some_role", :permissions => ["edit_profile"] }
  18 + role = Role.where(:name => 'some_role').first
  19 +
  20 + assert_not_nil role
  21 + assert_equal community.id, role.profile_id
  22 + end
  23 +
  24 + should 'not create a custom role without permission' do
  25 + community = fast_create(Community)
  26 + moderator = create_user_with_permission('profile_admin', 'edit_profile', community)
  27 + login_as :profile_admin
  28 + post :create, :profile => community.identifier, :role => {:name => "new_admin", :permissions => ["edit_profile"] }
  29 +
  30 + assert_response 403
  31 + assert_template 'access_denied'
  32 +
  33 + role = Role.where(:name => 'new_admin')
  34 +
  35 + assert_empty role
  36 + end
  37 +
  38 +
  39 + should 'delete a custom role not used' do
  40 + community = fast_create(Community)
  41 + admin = create_user_with_permission('admin_user', 'manage_custom_roles', community)
  42 + login_as :admin_user
  43 + role = Role.create!({:name => 'delete_article', :key => 'profile_delete_article', :profile_id => community.id, :environment => Environment.default}, :without_protection => true)
  44 + post :remove , :profile => community.identifier, :id => role.id
  45 +
  46 + assert_response :redirect
  47 + assert_redirected_to :action => 'index'
  48 +
  49 + assert_not_includes Role.all, role
  50 + end
  51 +
  52 + should 'delete a custom role being used' do
  53 + community = fast_create(Community)
  54 + admin = create_user_with_permission('admin_user', 'manage_custom_roles', community)
  55 + login_as :admin_user
  56 + role = Role.create!({:name => 'delete_article', :key => 'profile_delete_article', :profile_id => community.id, :environment => Environment.default}, :without_protection => true)
  57 + admin.add_role(role, community)
  58 + moderator_role = Role.find_by_name("moderator")
  59 +
  60 + assert_not_includes community.members_by_role(moderator_role), admin
  61 +
  62 + post :remove , :profile => community.identifier, :id => role.id, :roles => [moderator_role.id]
  63 +
  64 + assert_response :redirect
  65 + assert_redirected_to :action => 'index'
  66 +
  67 + assert_not_includes Role.all, role
  68 + assert_includes community.members_by_role(moderator_role), admin
  69 + end
  70 +
  71 + should 'assign a custom role to single user' do
  72 + community = fast_create(Community)
  73 + admin = create_user_with_permission('admin_user', 'manage_custom_roles', community)
  74 + login_as :admin_user
  75 + role = Role.create!({:name => 'delete_article', :key => 'profile_delete_article', :profile_id => community.id, :environment => Environment.default}, :without_protection => true)
  76 +
  77 + assert_not_includes community.members_by_role(role), admin
  78 +
  79 + post :define, :profile => community.identifier, :id => role.id, :assign_role_by => "members", :person_id => admin.id
  80 +
  81 + assert_includes community.members_by_role(role), admin
  82 + end
  83 +
  84 + should 'replace a role with a custom role' do
  85 + community = fast_create(Community)
  86 + admin = create_user_with_permission('admin_user', 'manage_custom_roles', community)
  87 + moderator = create_user_with_permission('profile_admin', 'edit_profile', community)
  88 + login_as :admin_user
  89 + role = Role.create!({:name => 'delete_article', :key => 'profile_delete_article', :profile_id => community.id, :environment => Environment.default}, :without_protection => true)
  90 + moderator_role = Role.find_by_name("moderator")
  91 + admin.add_role(moderator_role, community)
  92 +
  93 + assert_not_includes community.members_by_role(role), admin
  94 +
  95 + assert_not_includes community.members_by_role(role), moderator
  96 + assert_not_includes community.members_by_role(moderator_role), moderator
  97 +
  98 + post :define, :profile => community.identifier, :id => role.id, :assign_role_by => "roles", :selected_role => moderator_role.id
  99 +
  100 + assert_not_includes community.members_by_role(moderator_role), admin
  101 + assert_includes community.members_by_role(role), admin
  102 +
  103 + assert_not_includes community.members_by_role(role), moderator
  104 + assert_not_includes community.members_by_role(moderator_role), moderator
  105 + end
  106 +end
test/functional/spam_controller_test.rb
@@ -10,7 +10,7 @@ class SpamControllerTest &lt; ActionController::TestCase @@ -10,7 +10,7 @@ class SpamControllerTest &lt; ActionController::TestCase
10 @article = fast_create(TextileArticle, :profile_id => @community.id) 10 @article = fast_create(TextileArticle, :profile_id => @community.id)
11 @spam_comment = fast_create(Comment, :source_id => @article.id, :spam => true, :name => 'foo', :email => 'foo@example.com') 11 @spam_comment = fast_create(Comment, :source_id => @article.id, :spam => true, :name => 'foo', :email => 'foo@example.com')
12 12
13 - @spam_suggest_article = SuggestArticle.create!(:name => 'spammer', :article_name => 'Spam article', :email => 'spammer@shady.place', :article_body => "Something you don't need", :target => @community, :spam => true) 13 + @spam_suggest_article = SuggestArticle.create!(:name => 'spammer', :article => {:name => 'Spam article', :body => "Something you don't need"}, :email => 'spammer@shady.place', :target => @community, :spam => true)
14 login_as @profile.identifier 14 login_as @profile.identifier
15 end 15 end
16 16
test/functional/tasks_controller_test.rb
@@ -264,11 +264,11 @@ class TasksControllerTest &lt; ActionController::TestCase @@ -264,11 +264,11 @@ class TasksControllerTest &lt; ActionController::TestCase
264 c = fast_create(Community) 264 c = fast_create(Community)
265 c.add_admin profile 265 c.add_admin profile
266 @controller.stubs(:profile).returns(c) 266 @controller.stubs(:profile).returns(c)
267 - t = SuggestArticle.create!(:article_name => 'test name', :article_abstract => 'test abstract', :article_body => 'test body', :name => 'some name', :email => 'test@localhost.com', :target => c) 267 + t = SuggestArticle.create!(:article => {:name => 'test name', :abstract => 'test abstract', :body => 'test body'}, :name => 'some name', :email => 'test@localhost.com', :target => c)
268 268
269 get :index 269 get :index
270 - assert_tag :tag => 'textarea', :content => /test abstract/, :attributes => { :name => /article_abstract/, :class => 'mceEditor' }  
271 - assert_tag :tag => 'textarea', :content => /test body/, :attributes => { :name => /article_body/, :class => 'mceEditor' } 270 + assert_tag :tag => 'textarea', :content => /test abstract/, :attributes => { :name => /tasks\[#{t.id}\]\[task\]\[article\]\[abstract\]/, :class => 'mceEditor' }
  271 + assert_tag :tag => 'textarea', :content => /test body/, :attributes => { :name => /tasks\[#{t.id}\]\[task\]\[article\]\[body\]/, :class => 'mceEditor' }
272 end 272 end
273 273
274 should 'create TinyMceArticle article after finish approve suggested article task' do 274 should 'create TinyMceArticle article after finish approve suggested article task' do
@@ -276,7 +276,7 @@ class TasksControllerTest &lt; ActionController::TestCase @@ -276,7 +276,7 @@ class TasksControllerTest &lt; ActionController::TestCase
276 c = fast_create(Community) 276 c = fast_create(Community)
277 c.affiliate(profile, Profile::Roles.all_roles(profile.environment.id)) 277 c.affiliate(profile, Profile::Roles.all_roles(profile.environment.id))
278 @controller.stubs(:profile).returns(c) 278 @controller.stubs(:profile).returns(c)
279 - t = SuggestArticle.create!(:article_name => 'test name', :article_body => 'test body', :name => 'some name', :email => 'test@localhost.com', :target => c) 279 + t = SuggestArticle.create!(:article => {:name => 'test name', :body => 'test body'}, :name => 'some name', :email => 'test@localhost.com', :target => c)
280 280
281 post :close, :tasks => {t.id => { :task => {}, :decision => "finish"}} 281 post :close, :tasks => {t.id => { :task => {}, :decision => "finish"}}
282 assert_not_nil TinyMceArticle.find(:first) 282 assert_not_nil TinyMceArticle.find(:first)
@@ -288,16 +288,13 @@ class TasksControllerTest &lt; ActionController::TestCase @@ -288,16 +288,13 @@ class TasksControllerTest &lt; ActionController::TestCase
288 c.affiliate(profile, Profile::Roles.all_roles(profile.environment.id)) 288 c.affiliate(profile, Profile::Roles.all_roles(profile.environment.id))
289 @controller.stubs(:profile).returns(c) 289 @controller.stubs(:profile).returns(c)
290 t = SuggestArticle.new 290 t = SuggestArticle.new
291 - t.article_name = 'test name'  
292 - t.article_body = 'test body' 291 + t.article = {:name => 'test name', :body => 'test body', :source => 'http://test.com', :source_name => 'some source name'}
293 t.name = 'some name' 292 t.name = 'some name'
294 - t.source = 'http://test.com'  
295 - t.source_name = 'some source name'  
296 t.email = 'test@localhost.com' 293 t.email = 'test@localhost.com'
297 t.target = c 294 t.target = c
298 t.save! 295 t.save!
299 296
300 - post :close, :tasks => {t.id => { :task => {:article_name => 'new article name', :article_body => 'new body', :source => 'http://www.noosfero.com', :source_name => 'new source', :name => 'new name'}, :decision => "finish"}} 297 + post :close, :tasks => {t.id => { :task => {:article => {:name => 'new article name', :body => 'new body', :source => 'http://www.noosfero.com', :source_name => 'new source'}, :name => 'new name'}, :decision => "finish"}}
301 assert_equal 'new article name', TinyMceArticle.find(:first).name 298 assert_equal 'new article name', TinyMceArticle.find(:first).name
302 assert_equal 'new name', TinyMceArticle.find(:first).author_name 299 assert_equal 'new name', TinyMceArticle.find(:first).author_name
303 assert_equal 'new body', TinyMceArticle.find(:first).body 300 assert_equal 'new body', TinyMceArticle.find(:first).body
@@ -305,6 +302,51 @@ class TasksControllerTest &lt; ActionController::TestCase @@ -305,6 +302,51 @@ class TasksControllerTest &lt; ActionController::TestCase
305 assert_equal 'new source', TinyMceArticle.find(:first).source_name 302 assert_equal 'new source', TinyMceArticle.find(:first).source_name
306 end 303 end
307 304
  305 + should "display name from article suggestion when requestor was not setted" do
  306 + Task.destroy_all
  307 + c = fast_create(Community)
  308 + c.add_admin profile
  309 + @controller.stubs(:profile).returns(c)
  310 + t = SuggestArticle.create!(:article => {:name => 'test name', :abstract => 'test abstract', :body => 'test body'}, :name => 'some name', :email => 'test@localhost.com', :target => c)
  311 +
  312 + get :index
  313 + assert_select "#tasks_#{t.id}_task_name"
  314 + end
  315 +
  316 + should "append hidden tag with type value from article suggestion" do
  317 + Task.destroy_all
  318 + c = fast_create(Community)
  319 + c.add_admin profile
  320 + @controller.stubs(:profile).returns(c)
  321 + t = SuggestArticle.create!(:article => {:name => 'test name', :abstract => 'test abstract', :body => 'test body', :type => 'TextArticle'}, :name => 'some name', :email => 'test@localhost.com', :target => c)
  322 +
  323 + get :index
  324 + assert_select "#tasks_#{t.id}_task_article_type[value=TextArticle]"
  325 + end
  326 +
  327 + should "display parent_id selection from article suggestion with predefined value" do
  328 + Task.destroy_all
  329 + c = fast_create(Community)
  330 + c.add_admin profile
  331 + @controller.stubs(:profile).returns(c)
  332 + parent = fast_create(Folder, :profile_id => c.id)
  333 + t = SuggestArticle.create!(:article => {:name => 'test name', :abstract => 'test abstract', :body => 'test body', :parent_id => parent.id}, :name => 'some name', :email => 'test@localhost.com', :target => c)
  334 +
  335 + get :index
  336 + assert_select "#tasks_#{t.id}_task_article_parent_id option[value=#{parent.id}]"
  337 + end
  338 +
  339 + should "not display name from article suggestion when requestor was setted" do
  340 + Task.destroy_all
  341 + c = fast_create(Community)
  342 + c.add_admin profile
  343 + @controller.stubs(:profile).returns(c)
  344 + t = SuggestArticle.create!(:article => {:name => 'test name', :abstract => 'test abstract', :body => 'test body'}, :requestor => fast_create(Person), :target => c)
  345 +
  346 + get :index
  347 + assert_select "#tasks_#{t.id}_task_name", 0
  348 + end
  349 +
308 should "not crash if accessing close without tasks parameter" do 350 should "not crash if accessing close without tasks parameter" do
309 assert_nothing_raised do 351 assert_nothing_raised do
310 post :close 352 post :close
test/integration/routing_test.rb
@@ -272,4 +272,8 @@ class RoutingTest &lt; ActionController::IntegrationTest @@ -272,4 +272,8 @@ class RoutingTest &lt; ActionController::IntegrationTest
272 assert_routing('/embed/block/12345', :controller => 'embed', :action => 'block', :id => '12345') 272 assert_routing('/embed/block/12345', :controller => 'embed', :action => 'block', :id => '12345')
273 end 273 end
274 274
  275 + should 'accept ~ as placeholder for current user' do
  276 + assert_routing('/profile/~', :controller => 'profile', :profile => '~', :action => 'index')
  277 + end
  278 +
275 end 279 end
test/unit/article_test.rb
@@ -1715,6 +1715,18 @@ class ArticleTest &lt; ActiveSupport::TestCase @@ -1715,6 +1715,18 @@ class ArticleTest &lt; ActiveSupport::TestCase
1715 assert_equal 'bar.png', a.first_image 1715 assert_equal 'bar.png', a.first_image
1716 end 1716 end
1717 1717
  1718 + should 'get first image from having_image' do
  1719 + a = fast_create(Article,
  1720 + :body => '<p>Foo</p><p><img src="bar.png" /></p>',
  1721 + :abstract => '<p>Lead</p><p><img src="lead.png" /></p>'
  1722 + )
  1723 + img = {}
  1724 + img.expects(:present?).returns true
  1725 + img.expects(:public_filename).returns 'pic.jpg'
  1726 + a.expects(:image).at_least_once.returns img
  1727 + assert_equal 'pic.jpg', a.first_image
  1728 + end
  1729 +
1718 should 'not get first image from anywhere' do 1730 should 'not get first image from anywhere' do
1719 a = fast_create(Article, :body => '<p>Foo</p><p>Bar</p>') 1731 a = fast_create(Article, :body => '<p>Foo</p><p>Bar</p>')
1720 assert_equal '', a.first_image 1732 assert_equal '', a.first_image
test/unit/block_test.rb
@@ -35,6 +35,24 @@ class BlockTest &lt; ActiveSupport::TestCase @@ -35,6 +35,24 @@ class BlockTest &lt; ActiveSupport::TestCase
35 assert Block.new.editable? 35 assert Block.new.editable?
36 end 36 end
37 37
  38 + should 'be editable if edit modes is all' do
  39 + block = Block.new
  40 + block.edit_modes = 'all'
  41 +
  42 + assert block.editable?
  43 + end
  44 +
  45 + should 'be movable by default' do
  46 + assert Block.new.movable?
  47 + end
  48 +
  49 + should 'be movable if move modes is all' do
  50 + block = Block.new
  51 + block.move_modes = 'all'
  52 +
  53 + assert block.movable?
  54 + end
  55 +
38 should 'have default titles' do 56 should 'have default titles' do
39 b = Block.new 57 b = Block.new
40 b.expects(:default_title).returns('my title') 58 b.expects(:default_title).returns('my title')
@@ -330,4 +348,11 @@ class BlockTest &lt; ActiveSupport::TestCase @@ -330,4 +348,11 @@ class BlockTest &lt; ActiveSupport::TestCase
330 block.save! 348 block.save!
331 assert !block.display_to_user?(person_friend) 349 assert !block.display_to_user?(person_friend)
332 end 350 end
  351 +
  352 + should 'get limit as a number when limit is string' do
  353 + block = RecentDocumentsBlock.new
  354 + block.settings[:limit] = '5'
  355 + assert block.get_limit.is_a?(Fixnum)
  356 + end
  357 +
333 end 358 end
test/unit/blog_helper_test.rb
@@ -20,30 +20,36 @@ class BlogHelperTest &lt; ActionView::TestCase @@ -20,30 +20,36 @@ class BlogHelperTest &lt; ActionView::TestCase
20 def _(s); s; end 20 def _(s); s; end
21 def h(s); s; end 21 def h(s); s; end
22 22
23 - should 'list published posts with class blog-post' do  
24 - blog.children << published_post = create(TextileArticle, :name => 'Post', :profile => profile, :parent => blog, :published => true)  
25 -  
26 - expects(:display_post).with(anything, anything).returns('POST')  
27 - expects(:content_tag).with('div', "POST<br style=\"clear:both\"/>", :class => 'blog-post position-1 first last odd-post-inner', :id => "post-#{published_post.id}").returns('POST')  
28 - expects(:content_tag).with('div', 'POST', {:class => 'odd-post'}).returns('RESULT')  
29 -  
30 - assert_equal 'RESULT', list_posts(blog.posts)  
31 - end  
32 -  
33 - should 'list even/odd posts with a different class' do  
34 - blog.children << older_post = create(TextileArticle, :name => 'First post', :profile => profile, :parent => blog, :published => true)  
35 -  
36 - blog.children << newer_post = create(TextileArticle, :name => 'Second post', :profile => profile, :parent => blog, :published => true)  
37 -  
38 - expects(:display_post).with(anything, anything).returns('POST').times(2)  
39 -  
40 - expects(:content_tag).with('div', "POST<br style=\"clear:both\"/>", :class => 'blog-post position-1 first odd-post-inner', :id => "post-#{newer_post.id}").returns('POST 1')  
41 - expects(:content_tag).with('div', "POST 1", :class => 'odd-post').returns('ODD-POST')  
42 -  
43 - expects(:content_tag).with('div', "POST<br style=\"clear:both\"/>", :class => 'blog-post position-2 last even-post-inner', :id => "post-#{older_post.id}").returns('POST 2')  
44 - expects(:content_tag).with('div', "POST 2", :class => 'even-post').returns('EVEN-POST')  
45 -  
46 - assert_equal "ODD-POST\n<hr class='sep-posts'/>\nEVEN-POST", list_posts(blog.posts) 23 + should 'list blog posts with identifiers and classes' do
  24 + blog.children << older_post = create(TextileArticle, :name => 'First post',
  25 + :profile => profile, :parent => blog, :published => true)
  26 + blog.children << some_post = create(TextileArticle, :name => 'Some post',
  27 + :profile => profile, :parent => blog, :published => true)
  28 + blog.children << hidden_post = create(TextileArticle, :name => 'Hidden post',
  29 + :profile => profile, :parent => blog, :published => false)
  30 + blog.children << newer_post = create(TextileArticle, :name => 'Last post',
  31 + :profile => profile, :parent => blog, :published => true)
  32 +
  33 + def content_tag(tag, content_or_options_with_block = nil, options = nil, &block)
  34 + if block_given?
  35 + options = content_or_options_with_block
  36 + content = block.call
  37 + else
  38 + content = content_or_options_with_block
  39 + end
  40 + options ||= {}
  41 + "<#{tag}#{options.map{|k,v| " #{k}=\"#{[v].flatten.join(' ')}\""}.join}>#{content}</#{tag}>"
  42 + end
  43 +
  44 + html = HTML::Document.new(list_posts(blog.posts)).root
  45 + assert_select html, "div#post-#{newer_post.id}.blog-post.position-1.first.odd-post" +
  46 + " > div.odd-post-inner.blog-post-inner > .title", 'Last post'
  47 + assert_select html, "div#post-#{hidden_post.id}.blog-post.position-2.not-published.even-post" +
  48 + " > div.even-post-inner.blog-post-inner > .title", 'Hidden post'
  49 + assert_select html, "div#post-#{some_post.id}.blog-post.position-3.odd-post" +
  50 + " > div.odd-post-inner.blog-post-inner > .title", 'Some post'
  51 + assert_select html, "div#post-#{older_post.id}.blog-post.position-4.last.even-post" +
  52 + " > div.even-post-inner.blog-post-inner > .title", 'First post'
47 end 53 end
48 54
49 55
test/unit/boxes_helper_test.rb
@@ -123,24 +123,24 @@ class BoxesHelperTest &lt; ActionView::TestCase @@ -123,24 +123,24 @@ class BoxesHelperTest &lt; ActionView::TestCase
123 display_box_content(box, '') 123 display_box_content(box, '')
124 end 124 end
125 125
126 - should 'not show move options on block when block is fixed' do 126 + should 'not show move options on block when block has no permission to edit' do
127 p = create_user_with_blocks 127 p = create_user_with_blocks
128 128
129 b = p.blocks.select{|bk| !bk.kind_of?(MainBlock) }[0] 129 b = p.blocks.select{|bk| !bk.kind_of?(MainBlock) }[0]
130 - b.fixed = true 130 + b.move_modes = "none"
131 b.save! 131 b.save!
132 132
133 stubs(:environment).returns(p.environment) 133 stubs(:environment).returns(p.environment)
134 stubs(:user).returns(p) 134 stubs(:user).returns(p)
135 135
136 - assert_equal false, modifiable?(b) 136 + assert_equal false, movable?(b)
137 end 137 end
138 138
139 - should 'show move options on block when block is fixed and user is admin' do 139 + should 'show move options on block when block has no permission to edit and user is admin' do
140 p = create_user_with_blocks 140 p = create_user_with_blocks
141 141
142 b = p.blocks.select{|bk| !bk.kind_of?(MainBlock) }[0] 142 b = p.blocks.select{|bk| !bk.kind_of?(MainBlock) }[0]
143 - b.fixed = true 143 + b.edit_modes = "none"
144 b.save! 144 b.save!
145 145
146 p.environment.add_admin(p) 146 p.environment.add_admin(p)
@@ -148,7 +148,7 @@ class BoxesHelperTest &lt; ActionView::TestCase @@ -148,7 +148,7 @@ class BoxesHelperTest &lt; ActionView::TestCase
148 stubs(:environment).returns(p.environment) 148 stubs(:environment).returns(p.environment)
149 stubs(:user).returns(p) 149 stubs(:user).returns(p)
150 150
151 - assert_equal true, modifiable?(b) 151 + assert_equal true, movable?(b)
152 end 152 end
153 153
154 should 'consider boxes_limit without custom_design' do 154 should 'consider boxes_limit without custom_design' do
@@ -198,4 +198,16 @@ class BoxesHelperTest &lt; ActionView::TestCase @@ -198,4 +198,16 @@ class BoxesHelperTest &lt; ActionView::TestCase
198 assert_no_tag_in_string block_edit_buttons(block), :tag => 'a', :attributes => {:class => 'button icon-button icon-embed '} 198 assert_no_tag_in_string block_edit_buttons(block), :tag => 'a', :attributes => {:class => 'button icon-button icon-embed '}
199 end 199 end
200 200
  201 + should 'only show edit option on block' do
  202 + p = create_user_with_blocks
  203 +
  204 + b = p.blocks.select{|bk| !bk.kind_of?(MainBlock) }[0]
  205 + b.edit_modes = "only_edit"
  206 + b.save!
  207 +
  208 + stubs(:environment).returns(p.environment)
  209 + stubs(:user).returns(p)
  210 +
  211 + assert_equal false, b.editable?
  212 + end
201 end 213 end
test/unit/enterprise_test.rb
@@ -188,7 +188,7 @@ class EnterpriseTest &lt; ActiveSupport::TestCase @@ -188,7 +188,7 @@ class EnterpriseTest &lt; ActiveSupport::TestCase
188 inactive_template.save! 188 inactive_template.save!
189 189
190 active_template = create(Enterprise, :name => 'enteprise template', :identifier => 'enterprise_template') 190 active_template = create(Enterprise, :name => 'enteprise template', :identifier => 'enterprise_template')
191 - assert_equal 3, active_template.boxes.size 191 + assert_equal 4, active_template.boxes.size
192 192
193 e = Environment.default 193 e = Environment.default
194 e.inactive_enterprise_template = inactive_template 194 e.inactive_enterprise_template = inactive_template
@@ -400,7 +400,7 @@ class EnterpriseTest &lt; ActiveSupport::TestCase @@ -400,7 +400,7 @@ class EnterpriseTest &lt; ActiveSupport::TestCase
400 e.save! 400 e.save!
401 401
402 ent = create(Enterprise, :name => 'test enteprise', :identifier => 'test_ent') 402 ent = create(Enterprise, :name => 'test enteprise', :identifier => 'test_ent')
403 - assert_equal 3, ent.boxes.size 403 + assert_equal 4, ent.boxes.size
404 end 404 end
405 405
406 should 'collect the highlighted products with image' do 406 should 'collect the highlighted products with image' do
test/unit/highlights_block_test.rb
@@ -109,33 +109,14 @@ class HighlightsBlockTest &lt; ActiveSupport::TestCase @@ -109,33 +109,14 @@ class HighlightsBlockTest &lt; ActiveSupport::TestCase
109 end 109 end
110 110
111 should 'list images randomically' do 111 should 'list images randomically' do
112 - f1 = mock()  
113 - f1.expects(:public_filename).returns('address')  
114 - UploadedFile.expects(:find).with(1).returns(f1)  
115 - f2 = mock()  
116 - f2.expects(:public_filename).returns('address')  
117 - UploadedFile.expects(:find).with(2).returns(f2)  
118 - f3 = mock()  
119 - f3.expects(:public_filename).returns('address')  
120 - UploadedFile.expects(:find).with(3).returns(f3)  
121 - f4 = mock()  
122 - f4.expects(:public_filename).returns('address')  
123 - UploadedFile.expects(:find).with(4).returns(f4)  
124 - f5 = mock()  
125 - f5.expects(:public_filename).returns('address')  
126 - UploadedFile.expects(:find).with(5).returns(f5)  
127 block = HighlightsBlock.new 112 block = HighlightsBlock.new
128 - i1 = {:image_id => 1, :address => '/address', :position => 3, :title => 'address'}  
129 - i2 = {:image_id => 2, :address => '/address', :position => 1, :title => 'address'}  
130 - i3 = {:image_id => 3, :address => '/address', :position => 2, :title => 'address'}  
131 - i4 = {:image_id => 4, :address => '/address', :position => 5, :title => 'address'}  
132 - i5 = {:image_id => 5, :address => '/address', :position => 4, :title => 'address'}  
133 - block.images = [i1,i2,i3,i4,i5]  
134 block.shuffle = true 113 block.shuffle = true
135 - block.save!  
136 - block.reload  
137 - assert_equal [i1,i2,i3,i4,i5], block.images  
138 - assert_not_equal [i2,i3,i1,i4,i5], block.featured_images 114 +
  115 + images = []
  116 + block.expects(:get_images).returns(images)
  117 + images.expects(:shuffle).returns(images)
  118 +
  119 + block.featured_images
139 end 120 end
140 121
141 [Environment, Profile].each do |klass| 122 [Environment, Profile].each do |klass|
test/unit/layout_helper_test.rb
@@ -30,4 +30,17 @@ class LayoutHelperTest &lt; ActionView::TestCase @@ -30,4 +30,17 @@ class LayoutHelperTest &lt; ActionView::TestCase
30 assert_match /<link [^<]*href="\/designs\/themes\/my-theme\/global.css"/, css 30 assert_match /<link [^<]*href="\/designs\/themes\/my-theme\/global.css"/, css
31 end 31 end
32 32
  33 + should 'append javascript files of enabled plugins in noosfero javascripts' do
  34 + plugin1 = Noosfero::Plugin.new
  35 + plugin1.expects(:js_files).returns(['plugin1.js'])
  36 + plugin2 = Noosfero::Plugin.new
  37 + plugin2.expects(:js_files).returns('plugin2.js')
  38 + @plugins = [plugin1, plugin2]
  39 + expects(:environment).returns(Environment.default).at_least_once
  40 + expects(:profile).returns(nil).at_least_once
  41 + js_tag = noosfero_javascript
  42 + assert_match /plugin1\.js/, js_tag
  43 + assert_match /plugin2\.js/, js_tag
  44 + end
  45 +
33 end 46 end
test/unit/profile_test.rb
@@ -901,6 +901,8 @@ class ProfileTest &lt; ActiveSupport::TestCase @@ -901,6 +901,8 @@ class ProfileTest &lt; ActiveSupport::TestCase
901 901
902 should 'copy set of articles from a template' do 902 should 'copy set of articles from a template' do
903 template = create_user('test_template').person 903 template = create_user('test_template').person
  904 + template.is_template = true
  905 + template.save
904 template.articles.destroy_all 906 template.articles.destroy_all
905 a1 = fast_create(Article, :profile_id => template.id, :name => 'some xyz article') 907 a1 = fast_create(Article, :profile_id => template.id, :name => 'some xyz article')
906 a2 = fast_create(Article, :profile_id => template.id, :name => 'some child article', :parent_id => a1.id) 908 a2 = fast_create(Article, :profile_id => template.id, :name => 'some child article', :parent_id => a1.id)
@@ -934,6 +936,8 @@ class ProfileTest &lt; ActiveSupport::TestCase @@ -934,6 +936,8 @@ class ProfileTest &lt; ActiveSupport::TestCase
934 936
935 should 'copy homepage from template' do 937 should 'copy homepage from template' do
936 template = create_user('test_template').person 938 template = create_user('test_template').person
  939 + template.is_template = true
  940 + template.save
937 template.articles.destroy_all 941 template.articles.destroy_all
938 a1 = fast_create(Article, :profile_id => template.id, :name => 'some xyz article') 942 a1 = fast_create(Article, :profile_id => template.id, :name => 'some xyz article')
939 template.home_page = a1 943 template.home_page = a1
@@ -949,6 +953,8 @@ class ProfileTest &lt; ActiveSupport::TestCase @@ -949,6 +953,8 @@ class ProfileTest &lt; ActiveSupport::TestCase
949 953
950 should 'not advertise the articles copied from templates' do 954 should 'not advertise the articles copied from templates' do
951 template = create_user('test_template').person 955 template = create_user('test_template').person
  956 + template.is_template = true
  957 + template.save
952 template.articles.destroy_all 958 template.articles.destroy_all
953 a = fast_create(Article, :profile_id => template.id, :name => 'some xyz article') 959 a = fast_create(Article, :profile_id => template.id, :name => 'some xyz article')
954 960
@@ -962,7 +968,7 @@ class ProfileTest &lt; ActiveSupport::TestCase @@ -962,7 +968,7 @@ class ProfileTest &lt; ActiveSupport::TestCase
962 end 968 end
963 969
964 should 'copy set of boxes from profile template' do 970 should 'copy set of boxes from profile template' do
965 - template = fast_create(Profile) 971 + template = fast_create(Profile, :is_template => true)
966 template.boxes.destroy_all 972 template.boxes.destroy_all
967 template.boxes << Box.new 973 template.boxes << Box.new
968 template.boxes[0].blocks << Block.new 974 template.boxes[0].blocks << Block.new
@@ -977,7 +983,7 @@ class ProfileTest &lt; ActiveSupport::TestCase @@ -977,7 +983,7 @@ class ProfileTest &lt; ActiveSupport::TestCase
977 end 983 end
978 984
979 should 'copy layout template when applying template' do 985 should 'copy layout template when applying template' do
980 - template = fast_create(Profile) 986 + template = fast_create(Profile, :is_template => true)
981 template.layout_template = 'leftbar' 987 template.layout_template = 'leftbar'
982 template.save! 988 template.save!
983 989
@@ -989,7 +995,7 @@ class ProfileTest &lt; ActiveSupport::TestCase @@ -989,7 +995,7 @@ class ProfileTest &lt; ActiveSupport::TestCase
989 end 995 end
990 996
991 should 'copy blocks when applying template' do 997 should 'copy blocks when applying template' do
992 - template = fast_create(Profile) 998 + template = fast_create(Profile, :is_template => true)
993 template.boxes.destroy_all 999 template.boxes.destroy_all
994 template.boxes << Box.new 1000 template.boxes << Box.new
995 template.boxes[0].blocks << Block.new 1001 template.boxes[0].blocks << Block.new
@@ -1004,7 +1010,7 @@ class ProfileTest &lt; ActiveSupport::TestCase @@ -1004,7 +1010,7 @@ class ProfileTest &lt; ActiveSupport::TestCase
1004 end 1010 end
1005 1011
1006 should 'copy articles when applying template' do 1012 should 'copy articles when applying template' do
1007 - template = fast_create(Profile) 1013 + template = fast_create(Profile, :is_template => true)
1008 template.articles.create(:name => 'template article') 1014 template.articles.create(:name => 'template article')
1009 template.save! 1015 template.save!
1010 1016
@@ -1016,7 +1022,7 @@ class ProfileTest &lt; ActiveSupport::TestCase @@ -1016,7 +1022,7 @@ class ProfileTest &lt; ActiveSupport::TestCase
1016 end 1022 end
1017 1023
1018 should 'rename existing articles when applying template' do 1024 should 'rename existing articles when applying template' do
1019 - template = fast_create(Profile) 1025 + template = fast_create(Profile, :is_template => true)
1020 template.boxes.destroy_all 1026 template.boxes.destroy_all
1021 template.boxes << Box.new 1027 template.boxes << Box.new
1022 template.boxes[0].blocks << Block.new 1028 template.boxes[0].blocks << Block.new
@@ -1033,7 +1039,7 @@ class ProfileTest &lt; ActiveSupport::TestCase @@ -1033,7 +1039,7 @@ class ProfileTest &lt; ActiveSupport::TestCase
1033 end 1039 end
1034 1040
1035 should 'copy header when applying template' do 1041 should 'copy header when applying template' do
1036 - template = fast_create(Profile) 1042 + template = fast_create(Profile, :is_template => true)
1037 template[:custom_header] = '{name}' 1043 template[:custom_header] = '{name}'
1038 template.save! 1044 template.save!
1039 1045
@@ -1047,7 +1053,7 @@ class ProfileTest &lt; ActiveSupport::TestCase @@ -1047,7 +1053,7 @@ class ProfileTest &lt; ActiveSupport::TestCase
1047 end 1053 end
1048 1054
1049 should 'copy footer when applying template' do 1055 should 'copy footer when applying template' do
1050 - template = create(Profile, :address => 'Template address', :custom_footer => '{address}') 1056 + template = create(Profile, :address => 'Template address', :custom_footer => '{address}', :is_template => true)
1051 1057
1052 p = create(Profile, :address => 'Profile address') 1058 p = create(Profile, :address => 'Profile address')
1053 p.apply_template(template) 1059 p.apply_template(template)
@@ -1058,7 +1064,7 @@ class ProfileTest &lt; ActiveSupport::TestCase @@ -1058,7 +1064,7 @@ class ProfileTest &lt; ActiveSupport::TestCase
1058 end 1064 end
1059 1065
1060 should 'ignore failing validation when applying template' do 1066 should 'ignore failing validation when applying template' do
1061 - template = create(Profile, :layout_template => 'leftbar', :custom_footer => 'my custom footer', :custom_header => 'my custom header') 1067 + template = create(Profile, :layout_template => 'leftbar', :custom_footer => 'my custom footer', :custom_header => 'my custom header', :is_template => true)
1062 1068
1063 p = create(Profile) 1069 p = create(Profile)
1064 def p.validate 1070 def p.validate
@@ -1074,7 +1080,7 @@ class ProfileTest &lt; ActiveSupport::TestCase @@ -1074,7 +1080,7 @@ class ProfileTest &lt; ActiveSupport::TestCase
1074 end 1080 end
1075 1081
1076 should 'copy homepage when applying template' do 1082 should 'copy homepage when applying template' do
1077 - template = fast_create(Profile) 1083 + template = fast_create(Profile, :is_template => true)
1078 a1 = fast_create(Article, :profile_id => template.id, :name => 'some xyz article') 1084 a1 = fast_create(Article, :profile_id => template.id, :name => 'some xyz article')
1079 template.home_page = a1 1085 template.home_page = a1
1080 template.save! 1086 template.save!
@@ -1161,7 +1167,7 @@ class ProfileTest &lt; ActiveSupport::TestCase @@ -1161,7 +1167,7 @@ class ProfileTest &lt; ActiveSupport::TestCase
1161 end 1167 end
1162 1168
1163 should 'copy public/private setting from template' do 1169 should 'copy public/private setting from template' do
1164 - template = fast_create(Profile, :public_profile => false) 1170 + template = fast_create(Profile, :public_profile => false, :is_template => true)
1165 p = fast_create(Profile) 1171 p = fast_create(Profile)
1166 p.apply_template(template) 1172 p.apply_template(template)
1167 assert_equal false, p.public_profile 1173 assert_equal false, p.public_profile
test/unit/suggest_article_test.rb
@@ -13,16 +13,9 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase @@ -13,16 +13,9 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
13 13
14 should 'have the article_name' do 14 should 'have the article_name' do
15 t = SuggestArticle.new 15 t = SuggestArticle.new
16 - assert !t.errors[:article_name.to_s].present?  
17 - t.valid?  
18 - assert t.errors[:article_name.to_s].present?  
19 - end  
20 -  
21 - should 'have the article_body' do  
22 - t = SuggestArticle.new  
23 - assert !t.errors[:article_body.to_s].present?  
24 - t.valid?  
25 - assert t.errors[:article_body.to_s].present? 16 + assert !t.article_object.errors[:name].present?
  17 + t.article_object.valid?
  18 + assert t.article_object.errors[:name].present?
26 end 19 end
27 20
28 should 'have the email' do 21 should 'have the email' do
@@ -46,19 +39,12 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase @@ -46,19 +39,12 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
46 assert t.errors[:target_id.to_s].present? 39 assert t.errors[:target_id.to_s].present?
47 end 40 end
48 41
49 - should 'have the article_abstract' do  
50 - t = SuggestArticle.new  
51 - assert t.respond_to?(:article_abstract)  
52 - end  
53 -  
54 - should 'have the article_parent_id' do  
55 - t = SuggestArticle.new  
56 - assert t.respond_to?(:article_parent_id)  
57 - end  
58 -  
59 - should 'source be defined' do 42 + should 'have the article' do
60 t = SuggestArticle.new 43 t = SuggestArticle.new
61 - assert t.respond_to?(:source) 44 + assert t.respond_to?(:article_object)
  45 + assert !t.errors[:article_object].present?
  46 + t.valid?
  47 + assert t.errors[:article_object].present?
62 end 48 end
63 49
64 should 'create an article on with perfom method' do 50 should 'create an article on with perfom method' do
@@ -66,9 +52,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase @@ -66,9 +52,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
66 name = 'some name' 52 name = 'some name'
67 body = 'some body' 53 body = 'some body'
68 abstract = 'some abstract' 54 abstract = 'some abstract'
69 - t.article_name = name  
70 - t.article_body = body  
71 - t.article_abstract = abstract 55 + t.article = {:name => name, :body => body, :abstract => abstract}
72 t.target = @profile 56 t.target = @profile
73 count = TinyMceArticle.count 57 count = TinyMceArticle.count
74 t.perform 58 t.perform
@@ -77,8 +61,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase @@ -77,8 +61,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
77 61
78 should 'fill source name and URL into created article' do 62 should 'fill source name and URL into created article' do
79 t = build(SuggestArticle, :target => @profile) 63 t = build(SuggestArticle, :target => @profile)
80 - t.source_name = 'GNU project'  
81 - t.source = 'http://www.gnu.org/' 64 + t.article.merge!({:source_name => 'GNU project', :source => 'http://www.gnu.org/'})
82 t.perform 65 t.perform
83 66
84 article = TinyMceArticle.last 67 article = TinyMceArticle.last
@@ -95,7 +78,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase @@ -95,7 +78,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
95 78
96 should 'highlight created article' do 79 should 'highlight created article' do
97 t = build(SuggestArticle, :target => @profile) 80 t = build(SuggestArticle, :target => @profile)
98 - t.highlighted = true 81 + t.article[:highlighted] = true
99 t.perform 82 t.perform
100 83
101 article = TinyMceArticle.last(:conditions => { :name => t.article_name}) # just to be sure 84 article = TinyMceArticle.last(:conditions => { :name => t.article_name}) # just to be sure
@@ -132,19 +115,19 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase @@ -132,19 +115,19 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
132 end 115 end
133 116
134 should 'have target notification message' do 117 should 'have target notification message' do
135 - task = build(SuggestArticle, :target => @profile, :article_name => 'suggested article', :name => 'johndoe') 118 + task = build(SuggestArticle, :target => @profile, :article => {:name => 'suggested article'}, :name => 'johndoe')
136 119
137 assert_match(/#{task.name}.*suggested the publication of the article: #{task.subject}.*[\n]*.*to approve or reject/, task.target_notification_message) 120 assert_match(/#{task.name}.*suggested the publication of the article: #{task.subject}.*[\n]*.*to approve or reject/, task.target_notification_message)
138 end 121 end
139 122
140 should 'have target notification description' do 123 should 'have target notification description' do
141 - task = build(SuggestArticle,:target => @profile, :article_name => 'suggested article', :name => 'johndoe') 124 + task = build(SuggestArticle,:target => @profile, :article => {:name => 'suggested article'}, :name => 'johndoe')
142 125
143 assert_match(/#{task.name}.*suggested the publication of the article: #{task.subject}/, task.target_notification_description) 126 assert_match(/#{task.name}.*suggested the publication of the article: #{task.subject}/, task.target_notification_description)
144 end 127 end
145 128
146 should 'deliver target notification message' do 129 should 'deliver target notification message' do
147 - task = build(SuggestArticle, :target => @profile, :article_name => 'suggested article', :name => 'johndoe', :email => 'johndoe@example.com') 130 + task = build(SuggestArticle, :target => @profile, :article => {:name => 'suggested article'}, :name => 'johndoe', :email => 'johndoe@example.com')
148 131
149 email = TaskMailer.target_notification(task, task.target_notification_message).deliver 132 email = TaskMailer.target_notification(task, task.target_notification_message).deliver
150 133
@@ -160,7 +143,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase @@ -160,7 +143,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
160 should 'delegate spam detection to plugins' do 143 should 'delegate spam detection to plugins' do
161 Environment.default.enable_plugin(EverythingIsSpam) 144 Environment.default.enable_plugin(EverythingIsSpam)
162 145
163 - t1 = build(SuggestArticle, :target => @profile, :article_name => 'suggested article', :name => 'johndoe', :email => 'johndoe@example.com') 146 + t1 = build(SuggestArticle, :target => @profile, :article => {:name => 'suggested article'}, :name => 'johndoe', :email => 'johndoe@example.com')
164 147
165 EverythingIsSpam.any_instance.expects(:check_for_spam) 148 EverythingIsSpam.any_instance.expects(:check_for_spam)
166 149
@@ -189,7 +172,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase @@ -189,7 +172,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
189 should 'notify plugins of suggest_articles being marked as spam' do 172 should 'notify plugins of suggest_articles being marked as spam' do
190 Environment.default.enable_plugin(SpamNotification) 173 Environment.default.enable_plugin(SpamNotification)
191 174
192 - t = SuggestArticle.create!(:target => @profile, :article_name => 'suggested article', :name => 'johndoe', :article_body => 'wanna feel my body? my body baaaby', :email => 'johndoe@example.com') 175 + t = SuggestArticle.create!(:target => @profile, :article => {:name => 'suggested article', :body => 'wanna feel my body? my body baaaby'}, :name => 'johndoe', :email => 'johndoe@example.com')
193 176
194 t.spam! 177 t.spam!
195 process_delayed_job_queue 178 process_delayed_job_queue
@@ -200,7 +183,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase @@ -200,7 +183,7 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
200 should 'notify plugins of suggest_articles being marked as ham' do 183 should 'notify plugins of suggest_articles being marked as ham' do
201 Environment.default.enable_plugin(SpamNotification) 184 Environment.default.enable_plugin(SpamNotification)
202 185
203 - t = SuggestArticle.create!(:target => @profile, :article_name => 'suggested article', :name => 'johndoe', :article_body => 'wanna feel my body? my body baaaby', :email => 'johndoe@example.com') 186 + t = SuggestArticle.create!(:target => @profile, :article => {:name => 'suggested article', :body => 'wanna feel my body? my body baaaby'}, :name => 'johndoe', :email => 'johndoe@example.com')
204 187
205 t.ham! 188 t.ham!
206 process_delayed_job_queue 189 process_delayed_job_queue
@@ -219,10 +202,44 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase @@ -219,10 +202,44 @@ class SuggestArticleTest &lt; ActiveSupport::TestCase
219 end 202 end
220 203
221 should 'log spammer ip after marking comment as spam' do 204 should 'log spammer ip after marking comment as spam' do
222 - t = SuggestArticle.create!(:target => @profile, :article_name => 'suggested article', :name => 'johndoe', :article_body => 'wanna feel my body? my body baaaby', :email => 'johndoe@example.com', :ip_address => '192.168.0.1') 205 + t = SuggestArticle.create!(:target => @profile, :article => {:name => 'suggested article', :body => 'wanna feel my body? my body baaaby'}, :name => 'johndoe', :email => 'johndoe@example.com', :ip_address => '192.168.0.1')
223 t.spam! 206 t.spam!
224 log = File.open('log/test_spammers.log') 207 log = File.open('log/test_spammers.log')
225 assert_match "SuggestArticle-id: #{t.id} IP: 192.168.0.1", log.read 208 assert_match "SuggestArticle-id: #{t.id} IP: 192.168.0.1", log.read
226 end 209 end
227 210
  211 + should 'not require name and email when requestor is present' do
  212 + t = SuggestArticle.new(:requestor => fast_create(Person))
  213 + t.valid?
  214 + assert t.errors[:email].blank?
  215 + assert t.errors[:name].blank?
  216 + end
  217 +
  218 + should 'return name as sender when requestor is setted' do
  219 + person = fast_create(Person)
  220 + t = SuggestArticle.new(:requestor => person)
  221 + assert_equal person.name, t.sender
  222 + end
  223 +
  224 + should 'create an event on perfom method' do
  225 + t = SuggestArticle.new
  226 + t.article = {:name => 'name', :body => 'body', :type => 'Event'}
  227 + t.target = @profile
  228 + assert_difference "Event.count" do
  229 + t.perform
  230 + end
  231 + end
  232 +
  233 + should 'accept article type parameter' do
  234 + t = SuggestArticle.new
  235 + t.article = {:name => 'name', :body => 'body', :type => 'TextArticle'}
  236 + t.article_type == TextArticle
  237 + end
  238 +
  239 + should 'fallback to tinymce when type parameter is invalid' do
  240 + t = SuggestArticle.new
  241 + t.article = {:name => 'name', :body => 'body', :type => 'Comment'}
  242 + t.article_type == TinyMceArticle
  243 + end
  244 +
228 end 245 end
test/unit/user_mailer_test.rb
@@ -18,6 +18,14 @@ class UserMailerTest &lt; ActiveSupport::TestCase @@ -18,6 +18,14 @@ class UserMailerTest &lt; ActiveSupport::TestCase
18 end 18 end
19 end 19 end
20 20
  21 + should 'deliver profiles suggestions email' do
  22 + person = create_user('some-user').person
  23 + ProfileSuggestion.create!(:person => person, :suggestion =>
  24 +fast_create(Person))
  25 + email = UserMailer.profiles_suggestions_email(person).deliver
  26 + assert_match /profile\/some-user\/friends\/suggest/, email.body.to_s
  27 + end
  28 +
21 private 29 private
22 30
23 def read_fixture(action) 31 def read_fixture(action)
test/unit/user_test.rb
@@ -87,6 +87,14 @@ class UserTest &lt; ActiveSupport::TestCase @@ -87,6 +87,14 @@ class UserTest &lt; ActiveSupport::TestCase
87 assert_equal person_count + 1, Person.count 87 assert_equal person_count + 1, Person.count
88 end 88 end
89 89
  90 + def test_should_create_person_with_identifier_different_from_login
  91 + user = User.create!(:login => 'new_user', :email => 'new_user@example.com', :password => 'test', :password_confirmation => 'test', :person_data => {:identifier => "new_test"})
  92 +
  93 + assert Person.exists?(['user_id = ?', user.id])
  94 +
  95 + assert user.login != user.person.identifier
  96 + end
  97 +
90 def test_login_validation 98 def test_login_validation
91 u = User.new 99 u = User.new
92 u.valid? 100 u.valid?
@@ -355,7 +363,7 @@ class UserTest &lt; ActiveSupport::TestCase @@ -355,7 +363,7 @@ class UserTest &lt; ActiveSupport::TestCase
355 Person.any_instance.stubs(:created_at).returns(DateTime.parse('16-08-2010')) 363 Person.any_instance.stubs(:created_at).returns(DateTime.parse('16-08-2010'))
356 expected_hash = { 364 expected_hash = {
357 'login' => 'x_and_y', 'is_admin' => true, 'since_month' => 8, 365 'login' => 'x_and_y', 'is_admin' => true, 'since_month' => 8,
358 - 'chat_enabled' => false, 'since_year' => 2010, 'email_domain' => nil, 366 + 'chat_enabled' => false, 'since_year' => 2010, 'email_domain' => nil,
359 'amount_of_friends' => 0, 'friends_list' => {}, 'enterprises' => [], 367 'amount_of_friends' => 0, 'friends_list' => {}, 'enterprises' => [],
360 } 368 }
361 369
@@ -546,6 +554,7 @@ class UserTest &lt; ActiveSupport::TestCase @@ -546,6 +554,7 @@ class UserTest &lt; ActiveSupport::TestCase
546 554
547 should 'delay activation check with custom time' do 555 should 'delay activation check with custom time' do
548 NOOSFERO_CONF.stubs(:[]).with('hours_until_user_activation_check').returns(240) 556 NOOSFERO_CONF.stubs(:[]).with('hours_until_user_activation_check').returns(240)
  557 + NOOSFERO_CONF.stubs(:[]).with('exclude_profile_identifier_pattern')
549 user = new_user 558 user = new_user
550 job = Delayed::Job.last 559 job = Delayed::Job.last
551 assert_match /UserActivationJob/, job.handler 560 assert_match /UserActivationJob/, job.handler
util/debian-install/Vagrantfile
@@ -13,9 +13,11 @@ else @@ -13,9 +13,11 @@ else
13 local_debs = Dir.glob('*.deb') 13 local_debs = Dir.glob('*.deb')
14 debs.each do |f| 14 debs.each do |f|
15 fn = File.basename(f) 15 fn = File.basename(f)
16 - if local_debs.include?(fn)  
17 - local_debs.delete(fn)  
18 - else 16 +
  17 + local_debs.delete(fn)
  18 +
  19 + if File.stat(f) != File.stat(fn)
  20 + FileUtils::Verbose.rm_f(fn)
19 FileUtils::Verbose.ln f, '.' 21 FileUtils::Verbose.ln f, '.'
20 end 22 end
21 end 23 end
util/debian-install/install
@@ -61,19 +61,35 @@ deb http://download.noosfero.org/debian/wheezy-test ./ @@ -61,19 +61,35 @@ deb http://download.noosfero.org/debian/wheezy-test ./
61 deb-src http://download.noosfero.org/debian/wheezy-test ./ 61 deb-src http://download.noosfero.org/debian/wheezy-test ./
62 EOF 62 EOF
63 63
  64 +sed -e 's/wheezy/&-backports/' \
  65 + /etc/apt/sources.list > /etc/apt/sources.list.d/backports.list
  66 +
64 export DEBIAN_FRONTEND=noninteractive 67 export DEBIAN_FRONTEND=noninteractive
65 68
  69 +# local debs
  70 +if [ -n "$(find /vagrant -name '*.deb')" ]; then
  71 + apt-get install -qy apt-utils bzip2
  72 + (
  73 + rm -rf /opt/noosfero
  74 + mkdir /opt/noosfero
  75 + cp /vagrant/*.deb /opt/noosfero
  76 + cd /opt/noosfero
  77 + apt-ftparchive packages . > Packages
  78 + cat Packages | gzip - > Packages.gz
  79 + cat Packages | bzip2 - > Packages.bz2
  80 + apt-ftparchive release . > Release
  81 + echo 'deb [trusted=yes] file:///opt/noosfero ./' > /etc/apt/sources.list.d/local.list
  82 + )
  83 +else
  84 + rm -f /etc/apt/sources.list.d/local.list
  85 +fi
  86 +
66 apt-get update 87 apt-get update
67 apt-get dist-upgrade -qy 88 apt-get dist-upgrade -qy
68 -apt-get install -qy postgresql ruby1.8 89 +apt-get install -qy postgresql
69 90
70 -if dpkg --unpack /vagrant/noosfero_*.deb /vagrant/noosfero-apache_*.deb; then  
71 - apt-cache policy noosfero  
72 - apt-get install -qyf  
73 -else  
74 - apt-cache policy noosfero  
75 - apt-get install -qy noosfero noosfero-apache  
76 -fi 91 +apt-cache policy noosfero
  92 +apt-get install -qy noosfero noosfero-apache
77 93
78 a2dissite 000-default 94 a2dissite 000-default
79 service apache2 reload 95 service apache2 reload
vendor/plugins/access_control/lib/role.rb
@@ -4,6 +4,7 @@ class Role &lt; ActiveRecord::Base @@ -4,6 +4,7 @@ class Role &lt; ActiveRecord::Base
4 4
5 has_many :role_assignments, :dependent => :destroy 5 has_many :role_assignments, :dependent => :destroy
6 belongs_to :environment 6 belongs_to :environment
  7 + belongs_to :organization
7 serialize :permissions, Array 8 serialize :permissions, Array
8 validates_presence_of :name 9 validates_presence_of :name
9 validates_uniqueness_of :name, :scope => :environment_id 10 validates_uniqueness_of :name, :scope => :environment_id