Commit d0561132a9af7bcd87550258ef5e4358b6c0ea0c

Authored by Daniela Feitosa
2 parents abdf6fab 49e6135e

Merge branch 'stable'

Conflicts:
	app/controllers/my_profile/profile_themes_controller.rb
	test/unit/comment_test.rb
	vendor/plugins/action_tracker_has_comments/init.rb
app/controllers/admin/users_controller.rb
@@ -7,7 +7,7 @@ class UsersController < AdminController @@ -7,7 +7,7 @@ class UsersController < AdminController
7 include UsersHelper 7 include UsersHelper
8 8
9 def index 9 def index
10 - @filter = params[:filter] 10 + @filter = params[:filter] || 'all_users'
11 scope = environment.people.no_templates 11 scope = environment.people.no_templates
12 if @filter == 'admin_users' 12 if @filter == 'admin_users'
13 scope = scope.admins 13 scope = scope.admins
@@ -16,6 +16,7 @@ class UsersController < AdminController @@ -16,6 +16,7 @@ class UsersController < AdminController
16 elsif @filter == 'deactivated_users' 16 elsif @filter == 'deactivated_users'
17 scope = scope.deactivated 17 scope = scope.deactivated
18 end 18 end
  19 + scope = scope.order('name ASC')
19 @q = params[:q] 20 @q = params[:q]
20 @collection = find_by_contents(:people, scope, @q, {:per_page => per_page, :page => params[:npage]})[:results] 21 @collection = find_by_contents(:people, scope, @q, {:per_page => per_page, :page => params[:npage]})[:results]
21 end 22 end
app/controllers/application_controller.rb
@@ -21,6 +21,7 @@ class ApplicationController < ActionController::Base @@ -21,6 +21,7 @@ class ApplicationController < ActionController::Base
21 include ApplicationHelper 21 include ApplicationHelper
22 layout :get_layout 22 layout :get_layout
23 def get_layout 23 def get_layout
  24 + return nil if request.format == :js
24 theme_layout = theme_option(:layout) 25 theme_layout = theme_option(:layout)
25 if theme_layout 26 if theme_layout
26 theme_view_file('layouts/'+theme_layout) || theme_layout 27 theme_view_file('layouts/'+theme_layout) || theme_layout
app/controllers/box_organizer_controller.rb
@@ -70,7 +70,7 @@ class BoxOrganizerController < ApplicationController @@ -70,7 +70,7 @@ class BoxOrganizerController < ApplicationController
70 else 70 else
71 @center_block_types = (Box.acceptable_center_blocks & available_blocks) + plugins.dispatch(:extra_blocks, :type => boxes_holder.class, :position => 1) 71 @center_block_types = (Box.acceptable_center_blocks & available_blocks) + plugins.dispatch(:extra_blocks, :type => boxes_holder.class, :position => 1)
72 @side_block_types = (Box.acceptable_side_blocks & available_blocks) + plugins.dispatch(:extra_blocks, :type => boxes_holder.class, :position => [2,3]) 72 @side_block_types = (Box.acceptable_side_blocks & available_blocks) + plugins.dispatch(:extra_blocks, :type => boxes_holder.class, :position => [2,3])
73 - @boxes = boxes_holder.boxes 73 + @boxes = boxes_holder.boxes.with_position
74 render :action => 'add_block', :layout => false 74 render :action => 'add_block', :layout => false
75 end 75 end
76 end 76 end
app/helpers/boxes_helper.rb
@@ -39,7 +39,7 @@ module BoxesHelper @@ -39,7 +39,7 @@ module BoxesHelper
39 end 39 end
40 40
41 def display_boxes(holder, main_content) 41 def display_boxes(holder, main_content)
42 - boxes = holder.boxes.first(holder.boxes_limit) 42 + boxes = holder.boxes.with_position.first(holder.boxes_limit)
43 content = boxes.reverse.map { |item| display_box(item, main_content) }.join("\n") 43 content = boxes.reverse.map { |item| display_box(item, main_content) }.join("\n")
44 content = main_content if (content.blank?) 44 content = main_content if (content.blank?)
45 45
app/models/box.rb
@@ -5,6 +5,8 @@ class Box < ActiveRecord::Base @@ -5,6 +5,8 @@ class Box < ActiveRecord::Base
5 5
6 include Noosfero::Plugin::HotSpot 6 include Noosfero::Plugin::HotSpot
7 7
  8 + named_scope :with_position, :conditions => ['boxes.position > 0']
  9 +
8 def environment 10 def environment
9 owner ? (owner.kind_of?(Environment) ? owner : owner.environment) : nil 11 owner ? (owner.kind_of?(Environment) ? owner : owner.environment) : nil
10 end 12 end
app/models/environment.rb
@@ -186,7 +186,7 @@ class Environment < ActiveRecord::Base @@ -186,7 +186,7 @@ class Environment < ActiveRecord::Base
186 has_many :product_categories, :conditions => { :type => 'ProductCategory'} 186 has_many :product_categories, :conditions => { :type => 'ProductCategory'}
187 has_many :regions 187 has_many :regions
188 188
189 - has_many :roles 189 + has_many :roles, :dependent => :destroy
190 190
191 has_many :qualifiers 191 has_many :qualifiers
192 has_many :certifiers 192 has_many :certifiers
app/views/blocks/location.html.erb
@@ -3,7 +3,6 @@ @@ -3,7 +3,6 @@
3 <div class='the-localization-map'> 3 <div class='the-localization-map'>
4 <img src="https://maps.google.com/maps/api/staticmap?center=<%=profile.lat%>,<%=profile.lng%>&zoom=<%=block.zoom%>&size=190x250&maptype=<%=block.map_type%>&markers=<%=profile.lat%>,<%=profile.lng%>&sensor=false"/> 4 <img src="https://maps.google.com/maps/api/staticmap?center=<%=profile.lat%>,<%=profile.lng%>&zoom=<%=block.zoom%>&size=190x250&maptype=<%=block.map_type%>&markers=<%=profile.lat%>,<%=profile.lng%>&sensor=false"/>
5 </div> 5 </div>
6 -</div>  
7 <% else %> 6 <% else %>
8 <i><%= _('This profile has no geographical position registered.') %></i> 7 <i><%= _('This profile has no geographical position registered.') %></i>
9 <% end %> 8 <% end %>
debian/changelog
  1 +noosfero (0.46.1) unstable; urgency=low
  2 +
  3 + * Bugfixes release
  4 +
  5 + -- Daniela Soares Feitosa <daniela@colivre.coop.br> Fri, 07 Mar 2014 10:33:11 +0000
  6 +
1 noosfero (0.46.0) unstable; urgency=low 7 noosfero (0.46.0) unstable; urgency=low
2 8
3 * New features release 9 * New features release
lib/noosfero.rb
@@ -3,7 +3,7 @@ require &#39;fast_gettext&#39; @@ -3,7 +3,7 @@ require &#39;fast_gettext&#39;
3 3
4 module Noosfero 4 module Noosfero
5 PROJECT = 'noosfero' 5 PROJECT = 'noosfero'
6 - VERSION = '0.46.0' 6 + VERSION = '0.46.1'
7 7
8 def self.pattern_for_controllers_in_directory(dir) 8 def self.pattern_for_controllers_in_directory(dir)
9 disjunction = controllers_in_directory(dir).join('|') 9 disjunction = controllers_in_directory(dir).join('|')
lib/noosfero/core_ext.rb
1 require 'noosfero/core_ext/string' 1 require 'noosfero/core_ext/string'
2 require 'noosfero/core_ext/integer' 2 require 'noosfero/core_ext/integer'
  3 +require 'noosfero/core_ext/array'
3 require 'noosfero/core_ext/object' 4 require 'noosfero/core_ext/object'
4 require 'noosfero/core_ext/active_record' 5 require 'noosfero/core_ext/active_record'
lib/noosfero/core_ext/array.rb 0 → 100644
@@ -0,0 +1,9 @@ @@ -0,0 +1,9 @@
  1 +class Array
  2 +
  3 + def uniq_by
  4 + hash, array = {}, []
  5 + each { |i| hash[yield(i)] ||= (array << i) }
  6 + array
  7 + end
  8 +
  9 +end
lib/noosfero/plugin/routes.rb
@@ -15,12 +15,16 @@ Dir.glob(File.join(Rails.root, plugins_root, &#39;*&#39;, &#39;controllers&#39;)) do |controller @@ -15,12 +15,16 @@ Dir.glob(File.join(Rails.root, plugins_root, &#39;*&#39;, &#39;controllers&#39;)) do |controller
15 controllers_by_folder.each do |folder, controllers| 15 controllers_by_folder.each do |folder, controllers|
16 controllers.each do |controller| 16 controllers.each do |controller|
17 controller_name = controller.gsub("#{plugin_name}_plugin_",'') 17 controller_name = controller.gsub("#{plugin_name}_plugin_",'')
18 - map.connect "#{prefixes_by_folder[folder]}/#{plugin_name}/#{controller_name}/:action/:id", :controller => controller 18 + if %w[profile myprofile].include?(folder)
  19 + map.connect "#{prefixes_by_folder[folder]}/#{plugin_name}/#{controller_name}/:action/:id", :controller => controller, :profile => /#{Noosfero.identifier_format}/
  20 + else
  21 + map.connect "#{prefixes_by_folder[folder]}/#{plugin_name}/#{controller_name}/:action/:id", :controller => controller
  22 + end
19 end 23 end
20 end 24 end
21 25
22 map.connect 'plugin/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin' 26 map.connect 'plugin/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin'
23 - map.connect 'profile/:profile/plugin/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin_profile'  
24 - map.connect 'myprofile/:profile/plugin/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin_myprofile' 27 + map.connect 'profile/:profile/plugin/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin_profile', :profile => /#{Noosfero.identifier_format}/
  28 + map.connect 'myprofile/:profile/plugin/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin_myprofile', :profile => /#{Noosfero.identifier_format}/
25 map.connect 'admin/plugin/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin_admin' 29 map.connect 'admin/plugin/' + plugin_name + '/:action/:id', :controller => plugin_name + '_plugin_admin'
26 end 30 end
plugins/container_block/lib/container_block_plugin.rb
@@ -16,4 +16,8 @@ class ContainerBlockPlugin &lt; Noosfero::Plugin @@ -16,4 +16,8 @@ class ContainerBlockPlugin &lt; Noosfero::Plugin
16 true 16 true
17 end 17 end
18 18
  19 + def js_files
  20 + 'container_block.js'
  21 + end
  22 +
19 end 23 end
plugins/container_block/lib/container_block_plugin/container_block.rb
@@ -7,6 +7,16 @@ class ContainerBlockPlugin::ContainerBlock &lt; Block @@ -7,6 +7,16 @@ class ContainerBlockPlugin::ContainerBlock &lt; Block
7 settings_items :container_box_id, :type => Integer, :default => nil 7 settings_items :container_box_id, :type => Integer, :default => nil
8 settings_items :children_settings, :type => Hash, :default => {} 8 settings_items :children_settings, :type => Hash, :default => {}
9 9
  10 + validate :no_cyclical_reference, :if => 'container_box_id.present?'
  11 +
  12 + def no_cyclical_reference
  13 + errors.add(:box_id, _('cyclical reference is not allowed.')) if box_id == container_box_id
  14 + end
  15 +
  16 + before_save do |b|
  17 + raise "cyclical reference is not allowed" if b.box_id == b.container_box_id && !b.container_box_id.blank?
  18 + end
  19 +
10 def self.description 20 def self.description
11 _('Container') 21 _('Container')
12 end 22 end
@@ -15,6 +25,10 @@ class ContainerBlockPlugin::ContainerBlock &lt; Block @@ -15,6 +25,10 @@ class ContainerBlockPlugin::ContainerBlock &lt; Block
15 _('This block acts as a container for another blocks') 25 _('This block acts as a container for another blocks')
16 end 26 end
17 27
  28 + def cacheable?
  29 + false
  30 + end
  31 +
18 def layout_template 32 def layout_template
19 nil 33 nil
20 end 34 end
@@ -24,8 +38,9 @@ class ContainerBlockPlugin::ContainerBlock &lt; Block @@ -24,8 +38,9 @@ class ContainerBlockPlugin::ContainerBlock &lt; Block
24 end 38 end
25 39
26 def create_box 40 def create_box
27 - box = Box.create!(:owner => owner)  
28 - settings[:container_box_id] = box.id 41 + container_box = Box.create!(:owner => owner)
  42 + container_box.update_attribute(:position, nil)
  43 + settings[:container_box_id] = container_box.id
29 save! 44 save!
30 end 45 end
31 46
plugins/container_block/public/container_block.js 0 → 100644
@@ -0,0 +1,28 @@ @@ -0,0 +1,28 @@
  1 +function enableMoveContainerChildren(container, box) {
  2 + var div = jQuery('#box-'+box+' > .block-outer > .block');
  3 + if(!div.is('.ui-resizable')) {
  4 + div.resizable({
  5 + handles: 'e, w',
  6 + containment: '#block-'+container+' .block-inner-2',
  7 + resize: function( event, ui ) {
  8 + ui.element.height('auto');
  9 + }
  10 + });
  11 + }
  12 +}
  13 +
  14 +function disableMoveContainerChildren(container, box) {
  15 + var div = jQuery('#box-'+box+' > .block-outer > .block');
  16 + if(div.is('.ui-resizable')) {
  17 + div.resizable('destroy');
  18 + }
  19 +}
  20 +
  21 +function containerChildrenWidth(container, box) {
  22 + widths = "";
  23 + jQuery('#box-'+box+' > .block-outer > .block').each(function(i) {
  24 + childId = jQuery(this).attr('id').match(/block-(\d+)/)[1];
  25 + widths+=childId+","+jQuery(this).width()+"|";
  26 + });
  27 + return "widths="+widths;
  28 +}
plugins/container_block/public/style.css
  1 +#box-organizer .container-block-plugin_container-block > .block-inner-1 > .block-inner-2 > .button-bar {
  2 + height: 22px;
  3 + padding-bottom: 0px;
  4 + width: auto;
  5 +}
  6 +
1 #content .boxes .container-block-plugin_container-block .container_block_child, .container-block-plugin_container-block .block-outer { 7 #content .boxes .container-block-plugin_container-block .container_block_child, .container-block-plugin_container-block .block-outer {
2 display: inline-block; 8 display: inline-block;
3 vertical-align: top; 9 vertical-align: top;
@@ -17,14 +23,10 @@ @@ -17,14 +23,10 @@
17 background-image: url(/designs/icons/default/Tango/16x16/actions/go-previous.png); 23 background-image: url(/designs/icons/default/Tango/16x16/actions/go-previous.png);
18 } 24 }
19 25
20 -#content .boxes .container-block-plugin_container-block .block {  
21 - outline-offset: -2px;  
22 -}  
23 -  
24 #content .boxes .container-block-plugin_container-block .block .ui-resizable-handle { 26 #content .boxes .container-block-plugin_container-block .block .ui-resizable-handle {
25 width: 10px; 27 width: 10px;
26 height: 28px; 28 height: 28px;
27 - z-index: 0; 29 + z-index: 1000;
28 } 30 }
29 31
30 #content .boxes .container-block-plugin_container-block .block .ui-resizable-e { 32 #content .boxes .container-block-plugin_container-block .block .ui-resizable-e {
@@ -37,6 +39,21 @@ @@ -37,6 +39,21 @@
37 background-image: url(/plugins/container_block/images/handle_w.png); 39 background-image: url(/plugins/container_block/images/handle_w.png);
38 } 40 }
39 41
40 -.container-block-plugin_container-block .button-bar .icon-resize { 42 +.container-block-plugin_container-block .container-block-button-bar .icon-resize {
41 background-image: url(/designs/icons/default/Tango/16x16/actions/view-fullscreen.png); 43 background-image: url(/designs/icons/default/Tango/16x16/actions/view-fullscreen.png);
42 } 44 }
  45 +
  46 +#box-organizer .block .container-block-button-bar {
  47 + right: 0px;
  48 + bottom: 0px;
  49 + height: auto;
  50 +}
  51 +
  52 +#box-organizer .container-block-plugin_container-block:hover .block {
  53 + outline: 1px dashed black;
  54 + outline-offset: -1px;
  55 +}
  56 +
  57 +.container-block-plugin_container-block .block-target {
  58 + background: #afd;
  59 +}
plugins/container_block/test/functional/container_block_home_controller_test.rb
@@ -31,6 +31,13 @@ class HomeControllerTest &lt; ActionController::TestCase @@ -31,6 +31,13 @@ class HomeControllerTest &lt; ActionController::TestCase
31 assert_tag :div, :attributes => { :class => 'block container-block-plugin_container-block' } 31 assert_tag :div, :attributes => { :class => 'block container-block-plugin_container-block' }
32 end 32 end
33 33
  34 + should 'display block title' do
  35 + @block.title = "Block Title"
  36 + @block.save!
  37 + get :index
  38 + assert_tag :div, :attributes => { :class => 'block container-block-plugin_container-block' }, :descendant => {:tag => 'h3', :attributes => { :class => "block-title"}, :content => @block.title }
  39 + end
  40 +
34 should 'display container children' do 41 should 'display container children' do
35 c1 = RawHTMLBlock.create!(:box => @block.container_box, :html => 'child1 content') 42 c1 = RawHTMLBlock.create!(:box => @block.container_box, :html => 'child1 content')
36 c2 = RawHTMLBlock.create!(:box => @block.container_box, :html => 'child2 content') 43 c2 = RawHTMLBlock.create!(:box => @block.container_box, :html => 'child2 content')
plugins/container_block/test/unit/block_test.rb
@@ -1,31 +0,0 @@ @@ -1,31 +0,0 @@
1 -require 'test_helper'  
2 -  
3 -class BlockTest < ActiveSupport::TestCase  
4 -  
5 - def setup  
6 - @environment = fast_create(Environment)  
7 - @box = Box.create!(:owner => @environment)  
8 - @container = ContainerBlockPlugin::ContainerBlock.create!(:box => @box)  
9 - end  
10 -  
11 - should 'return environment box if block owner is not a ContainerBlock' do  
12 - block = Block.create!(:box => @box)  
13 - assert_equal @box, block.box  
14 - end  
15 -  
16 - should 'return container box if block owner is a ContainerBlock' do  
17 - block = Block.create!(:box => @container.container_box)  
18 - assert_equal @container.container_box, block.box  
19 - end  
20 -  
21 - should 'return block owner if block onwer is not a ContainerBlock' do  
22 - block = Block.create!(:box => @box)  
23 - assert_equal @environment, block.owner  
24 - end  
25 -  
26 - should 'return environment as owner if block onwer is a ContainerBlock' do  
27 - block = Block.create!(:box => @container.container_box)  
28 - assert_equal @environment, block.owner  
29 - end  
30 -  
31 -end  
plugins/container_block/test/unit/container_block_plugin/container_block_test.rb
@@ -20,6 +20,11 @@ class ContainerBlockPlugin::ContainerBlockTest &lt; ActiveSupport::TestCase @@ -20,6 +20,11 @@ class ContainerBlockPlugin::ContainerBlockTest &lt; ActiveSupport::TestCase
20 assert @block.container_box_id 20 assert @block.container_box_id
21 end 21 end
22 22
  23 + should 'created box should have nil as position' do
  24 + @block.save!
  25 + assert_equal nil, @block.container_box.position
  26 + end
  27 +
23 should 'return created box' do 28 should 'return created box' do
24 @block.save! 29 @block.save!
25 assert @block.container_box 30 assert @block.container_box
@@ -89,4 +94,27 @@ class ContainerBlockPlugin::ContainerBlockTest &lt; ActiveSupport::TestCase @@ -89,4 +94,27 @@ class ContainerBlockPlugin::ContainerBlockTest &lt; ActiveSupport::TestCase
89 end 94 end
90 end 95 end
91 96
  97 + should 'not mess up with boxes positions when destroyed' do
  98 + env = fast_create(Environment)
  99 + box1 = fast_create(Box, :owner_id => env.id, :owner_type => 'Environment', :position => 1)
  100 + box2 = fast_create(Box, :owner_id => env.id, :owner_type => 'Environment', :position => 2)
  101 + box3 = fast_create(Box, :owner_id => env.id, :owner_type => 'Environment', :position => 3)
  102 + block = ContainerBlockPlugin::ContainerBlock.create!(:box => box1)
  103 + block.destroy
  104 + assert_equal [1, 2, 3], [box1.reload.position, box2.reload.position, box3.reload.position]
  105 + end
  106 +
  107 + should 'be able to change box' do
  108 + @block.save!
  109 + @block.box = Box.new(:owner => Environment.default)
  110 + @block.save!
  111 + end
  112 +
  113 + should 'not able to change box to be the same as container_box' do
  114 + @block.save!
  115 + @block.box = @block.container_box
  116 + @block.save
  117 + assert @block.errors.invalid?(:box_id)
  118 + end
  119 +
92 end 120 end
plugins/container_block/test/unit/environment_test.rb
@@ -1,32 +0,0 @@ @@ -1,32 +0,0 @@
1 -require 'test_helper'  
2 -  
3 -class EnvironmentTest < ActiveSupport::TestCase  
4 -  
5 - def setup  
6 - @environment = fast_create(Environment)  
7 -  
8 - @box = Box.create!(:owner => @environment)  
9 - @block = Block.create!(:box => @box)  
10 -  
11 - @container = ContainerBlockPlugin::ContainerBlock.create!(:box => @box)  
12 - end  
13 -  
14 - should 'return blocks as usual' do  
15 - assert_equal [@block, @container], @environment.blocks  
16 - end  
17 -  
18 - should 'return blocks with container children' do  
19 - child = Block.create!(:box => @container.container_box)  
20 - assert_equal [@block, @container, child], @environment.blocks  
21 - end  
22 -  
23 - should 'return block with id at find method' do  
24 - assert_equal @block, @environment.blocks.find(@block.id)  
25 - end  
26 -  
27 - should 'return child block with id at find method' do  
28 - child = Block.create!(:box => @container.container_box)  
29 - assert_equal child, @environment.blocks.find(child.id)  
30 - end  
31 -  
32 -end  
plugins/container_block/test/unit/profile_test.rb
@@ -1,32 +0,0 @@ @@ -1,32 +0,0 @@
1 -require 'test_helper'  
2 -  
3 -class ProfileTest < ActiveSupport::TestCase  
4 -  
5 - def setup  
6 - @profile = fast_create(Profile)  
7 -  
8 - @box = Box.create!(:owner => @profile)  
9 - @block = Block.create!(:box => @box)  
10 -  
11 - @container = ContainerBlockPlugin::ContainerBlock.create!(:box => @box)  
12 - end  
13 -  
14 - should 'return blocks as usual' do  
15 - assert_equal [@block, @container], @profile.blocks  
16 - end  
17 -  
18 - should 'return blocks with container children' do  
19 - child = Block.create!(:box => @container.container_box)  
20 - assert_equal [@block, @container, child], @profile.blocks  
21 - end  
22 -  
23 - should 'return block with id at find method' do  
24 - assert_equal @block, @profile.blocks.find(@block.id)  
25 - end  
26 -  
27 - should 'return child block with id at find method' do  
28 - child = Block.create!(:box => @container.container_box)  
29 - assert_equal child, @profile.blocks.find(child.id)  
30 - end  
31 -  
32 -end  
plugins/container_block/views/blocks/container.rhtml
1 <% edit_mode = @controller.send(:boxes_editor?) && @controller.send(:uses_design_blocks?) %> 1 <% edit_mode = @controller.send(:boxes_editor?) && @controller.send(:uses_design_blocks?) %>
2 <% box_decorator = edit_mode ? self : BoxesHelper::DontMoveBlocks %> 2 <% box_decorator = edit_mode ? self : BoxesHelper::DontMoveBlocks %>
3 3
  4 +<%= block_title(block.title) %>
4 5
5 <div class="box" id="box-<%= block.container_box.id %>"> 6 <div class="box" id="box-<%= block.container_box.id %>">
6 <%= display_box_content(block.container_box, nil) %> 7 <%= display_box_content(block.container_box, nil) %>
@@ -15,8 +16,18 @@ @@ -15,8 +16,18 @@
15 </style> 16 </style>
16 17
17 <% if edit_mode %> 18 <% if edit_mode %>
18 - <div class="button-bar">  
19 - <a href="#" onclick="toggleMoveContainerChildren(<%= block.id %>, <%= block.container_box.id %>); return false;" class="button icon-resize" title=<%= _('Resize blocks').to_json %>></a> 19 +
  20 + <script>
  21 + jQuery("#block-<%= block.id %>").hover(
  22 + function() {
  23 + enableMoveContainerChildren(<%= block.id %>, <%= block.container_box.id %>);
  24 + }, function() {
  25 + disableMoveContainerChildren(<%= block.id %>, <%= block.container_box.id %>);
  26 + }
  27 + );
  28 + </script>
  29 +
  30 + <div class="container-block-button-bar button-bar">
20 <%= link_to_remote '', :url => { :controller => @controller.boxes_holder.kind_of?(Environment) ? 'container_block_plugin_admin' : 'container_block_plugin_myprofile', :action => 'saveWidths', :id => block.id }, 31 <%= link_to_remote '', :url => { :controller => @controller.boxes_holder.kind_of?(Environment) ? 'container_block_plugin_admin' : 'container_block_plugin_myprofile', :action => 'saveWidths', :id => block.id },
21 :with => "containerChildrenWidth(#{block.id}, #{block.container_box.id})", 32 :with => "containerChildrenWidth(#{block.id}, #{block.container_box.id})",
22 :html => {:class => "button icon-save container_block_save", :id => "container_block_save_#{block.id}", :title => _('Save') }, 33 :html => {:class => "button icon-save container_block_save", :id => "container_block_save_#{block.id}", :title => _('Save') },
@@ -24,37 +35,4 @@ @@ -24,37 +35,4 @@
24 :loaded => "close_loading();", 35 :loaded => "close_loading();",
25 :complete => "display_notice(request.responseText);"%> 36 :complete => "display_notice(request.responseText);"%>
26 </div> 37 </div>
27 -  
28 - <script>  
29 - function toggleMoveContainerChildren(container, box) {  
30 - var div = jQuery('#box-'+box+' > .block-outer > .block');  
31 - var targetDiv = jQuery('#box-'+box+' .block-outer .block-target');  
32 - if(div.is('.ui-resizable')) {  
33 - targetDiv.show();  
34 - div.find("a").die("click");  
35 - div.resizable('destroy');  
36 - } else {  
37 - targetDiv.hide();  
38 - div.find("a").live("click", function(e) {  
39 - e.preventDefault();  
40 - });  
41 - div.resizable({  
42 - handles: 'e, w',  
43 - containment: '#block-'+container+' .block-inner-2',  
44 - resize: function( event, ui ) {  
45 - ui.element.height('auto');  
46 - }  
47 - });  
48 - }  
49 - }  
50 -  
51 - function containerChildrenWidth(container, box) {  
52 - widths = "";  
53 - jQuery('#box-'+box+' > .block-outer > .block').each(function(i) {  
54 - childId = jQuery(this).attr('id').match(/block-(\d+)/)[1];  
55 - widths+=childId+","+jQuery(this).width()+"|";  
56 - });  
57 - return "widths="+widths;  
58 - }  
59 - </script>  
60 <% end %> 38 <% end %>
plugins/require_auth_to_comment/public/hide_comment_form.js
1 (function($) { 1 (function($) {
2 $(window).bind('userDataLoaded', function(event, data) { 2 $(window).bind('userDataLoaded', function(event, data) {
3 - if (data.login || $('meta[name=profile.allow_unauthenticated_comments]').length > 0) { 3 + if (data.login || $('meta[name="profile.allow_unauthenticated_comments"]').length > 0) {
4 $('.post-comment-button').livequery(function() { 4 $('.post-comment-button').livequery(function() {
5 $(this).show(); 5 $(this).show();
6 }); 6 });
@@ -8,7 +8,7 @@ @@ -8,7 +8,7 @@
8 $(this).show(); 8 $(this).show();
9 }); 9 });
10 $('.comment-footer').livequery(function() { 10 $('.comment-footer').livequery(function() {
11 - $(this).show(); 11 + $(this).show();
12 }); 12 });
13 } 13 }
14 }); 14 });
public/stylesheets/application.css
  1 +/* browser fixes */
  2 +
  3 +img:-moz-broken {
  4 + -moz-force-broken-image-icon:1;
  5 +}
  6 +
  7 +/* general styles */
  8 +
1 body { 9 body {
2 padding: 0px; 10 padding: 0px;
3 margin: 0px; 11 margin: 0px;
@@ -1727,8 +1735,8 @@ a.button.disabled, input.disabled { @@ -1727,8 +1735,8 @@ a.button.disabled, input.disabled {
1727 display: none; 1735 display: none;
1728 } 1736 }
1729 1737
1730 -#box-organizer .block:focus .button-bar,  
1731 -#box-organizer .block:hover .button-bar { 1738 +#box-organizer .block-outer:focus .button-bar,
  1739 +#box-organizer .block-outer:hover .button-bar {
1732 display: block; 1740 display: block;
1733 } 1741 }
1734 1742
test/functional/profile_themes_controller_test.rb
@@ -310,4 +310,23 @@ class ProfileThemesControllerTest &lt; ActionController::TestCase @@ -310,4 +310,23 @@ class ProfileThemesControllerTest &lt; ActionController::TestCase
310 assert_no_tag :content => "Select theme" 310 assert_no_tag :content => "Select theme"
311 end 311 end
312 312
  313 + should 'not duplicate themes that are included by the user and by the environment' do
  314 + t1 = Theme.create('theme1')
  315 + t2 = Theme.create('theme2')
  316 + Environment.any_instance.stubs('themes').returns([t1,t2])
  317 + Theme.stubs(:approved_themes).returns([t2])
  318 +
  319 + get :index, :profile => "testinguser"
  320 + assert_equivalent [t1, t2], assigns(:themes)
  321 + end
  322 +
  323 + should 'sort themes by name' do
  324 + t1 = Theme.create('bill-theme')
  325 + t2 = Theme.create('ana-theme')
  326 + Theme.stubs(:approved_themes).returns([t1,t2])
  327 +
  328 + get :index, :profile => "testinguser"
  329 + assert_equal [t2, t1], assigns(:themes)
  330 + end
  331 +
313 end 332 end
test/functional/users_controller_test.rb
@@ -107,6 +107,21 @@ class UsersControllerTest &lt; ActionController::TestCase @@ -107,6 +107,21 @@ class UsersControllerTest &lt; ActionController::TestCase
107 assert_equal false, u.activated? 107 assert_equal false, u.activated?
108 end 108 end
109 109
  110 + should 'order users by name' do
  111 + create_user('jeremy')
  112 + create_user('bill')
  113 + create_user('ana')
  114 + create_user('creed')
  115 + get :index
  116 +
  117 + assert_order ['ana', 'bill', 'creed', 'jeremy'], assigns(:collection).map(&:name)
  118 + end
  119 +
  120 + should 'set filter to all_users by default' do
  121 + get :index
  122 + assert_equal 'all_users', assigns(:filter)
  123 + end
  124 +
110 should 'response as XML to export users' do 125 should 'response as XML to export users' do
111 get :download, :format => 'xml' 126 get :download, :format => 'xml'
112 assert_equal 'text/xml', @response.content_type 127 assert_equal 'text/xml', @response.content_type
test/test_helper.rb
@@ -177,6 +177,19 @@ class ActiveSupport::TestCase @@ -177,6 +177,19 @@ class ActiveSupport::TestCase
177 assert !tag, "expected no tag #{options.inspect}, but tag found in #{text.inspect}" 177 assert !tag, "expected no tag #{options.inspect}, but tag found in #{text.inspect}"
178 end 178 end
179 179
  180 + def assert_order(reference, original)
  181 + original.each do |value|
  182 + if reference.include?(value)
  183 + if reference.first == value
  184 + reference.shift
  185 + else
  186 + assert false, "'#{value}' was found before it should be on: #{original.inspect}"
  187 + end
  188 + end
  189 + end
  190 + assert reference.blank?, "The following elements are not in the collection: #{reference.inspect}"
  191 + end
  192 +
180 # For models that render views (blocks, articles, ...) 193 # For models that render views (blocks, articles, ...)
181 def render(*args) 194 def render(*args)
182 view_paths = @explicit_view_paths || ActionController::Base.view_paths 195 view_paths = @explicit_view_paths || ActionController::Base.view_paths
test/unit/array_core_ext_test.rb 0 → 100644
@@ -0,0 +1,11 @@ @@ -0,0 +1,11 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +# tests for Array core extension. See lib/noosfero/core_ext/array.rb
  4 +class StringCoreExtTest < ActiveSupport::TestCase
  5 +
  6 + should 'allow uniq by a block' do
  7 + array = [0,1,2,3,4,5,6]
  8 + assert_equal [0,1], array.uniq_by {|number| number%2 }
  9 + end
  10 +
  11 +end
test/unit/box_test.rb
@@ -140,4 +140,11 @@ class BoxTest &lt; ActiveSupport::TestCase @@ -140,4 +140,11 @@ class BoxTest &lt; ActiveSupport::TestCase
140 assert !blocks.include?('box-test_plugin-block') 140 assert !blocks.include?('box-test_plugin-block')
141 end 141 end
142 142
  143 + should 'list only boxes with a postion greater than zero' do
  144 + profile = fast_create(Profile)
  145 + box = fast_create(Box, :owner_id => profile.id, :owner_type => 'Profile', :position => 0)
  146 + box2 = fast_create(Box, :owner_id => profile.id, :owner_type => 'Profile', :position => 1)
  147 + assert_equal [box2], profile.boxes.with_position
  148 + end
  149 +
143 end 150 end
test/unit/boxes_helper_test.rb
@@ -13,7 +13,8 @@ class BoxesHelperTest &lt; ActiveSupport::TestCase @@ -13,7 +13,8 @@ class BoxesHelperTest &lt; ActiveSupport::TestCase
13 13
14 should 'include profile-specific header' do 14 should 'include profile-specific header' do
15 holder = mock 15 holder = mock
16 - holder.stubs(:boxes).returns([]) 16 + holder.stubs(:boxes).returns(boxes = [])
  17 + boxes.stubs(:with_position).returns([])
17 holder.stubs(:boxes_limit).returns(0) 18 holder.stubs(:boxes_limit).returns(0)
18 holder.stubs(:custom_header_expanded).returns('my custom header') 19 holder.stubs(:custom_header_expanded).returns('my custom header')
19 @controller.stubs(:boxes_holder).returns(holder) 20 @controller.stubs(:boxes_holder).returns(holder)
@@ -23,7 +24,8 @@ class BoxesHelperTest &lt; ActiveSupport::TestCase @@ -23,7 +24,8 @@ class BoxesHelperTest &lt; ActiveSupport::TestCase
23 24
24 should 'include profile-specific footer' do 25 should 'include profile-specific footer' do
25 holder = mock 26 holder = mock
26 - holder.stubs(:boxes).returns([]) 27 + holder.stubs(:boxes).returns(boxes = [])
  28 + boxes.stubs(:with_position).returns([])
27 holder.stubs(:boxes_limit).returns(0) 29 holder.stubs(:boxes_limit).returns(0)
28 holder.stubs(:custom_footer_expanded).returns('my custom footer') 30 holder.stubs(:custom_footer_expanded).returns('my custom footer')
29 @controller.stubs(:boxes_holder).returns(holder) 31 @controller.stubs(:boxes_holder).returns(holder)
test/unit/comment_test.rb
@@ -285,6 +285,37 @@ class CommentTest &lt; ActiveSupport::TestCase @@ -285,6 +285,37 @@ class CommentTest &lt; ActiveSupport::TestCase
285 assert_equal [c1,c3], c.reload.children 285 assert_equal [c1,c3], c.reload.children
286 end 286 end
287 287
  288 + should "return activities comments as a thread" do
  289 + person = fast_create(Person)
  290 + a = TextileArticle.create!(:profile => person, :name => 'My article', :body => 'Article body')
  291 + c0 = Comment.create!(:source => a, :body => 'My comment', :author => person)
  292 + c1 = Comment.create!(:reply_of_id => c0.id, :source => a, :body => 'bla', :author => person)
  293 + c2 = Comment.create!(:reply_of_id => c1.id, :source => a, :body => 'bla', :author => person)
  294 + c3 = Comment.create!(:reply_of_id => c0.id, :source => a, :body => 'bla', :author => person)
  295 + c4 = Comment.create!(:source => a, :body => 'My comment', :author => person)
  296 + result = a.activity.comments
  297 + assert_equal c0, result[0]
  298 + assert_equal [c1, c3], result[0].replies
  299 + assert_equal [c2], result[0].replies[0].replies
  300 + assert_equal c4, result[1]
  301 + assert result[1].replies.empty?
  302 + end
  303 +
  304 + should "return activities comments when some comment on thread is spam and not display its replies" do
  305 + person = fast_create(Person)
  306 + a = TextileArticle.create!(:profile => person, :name => 'My article', :body => 'Article body')
  307 + c0 = Comment.create(:source => a, :body => 'Root comment', :author => person)
  308 + c1 = Comment.create(:reply_of_id => c0.id, :source => a, :body => 'c1', :author => person)
  309 + c2 = Comment.create(:source => a, :body => 'c2', :author => person)
  310 + spam = Comment.create(:spam => true, :reply_of_id => c2.id, :source => a, :body => 'spam', :author => person)
  311 + spam_reply = Comment.create(:reply_of_id => spam.id, :source => a, :body => 'spam reply', :author => person)
  312 + result = a.activity.comments
  313 + assert_equal c0, result[0]
  314 + assert_equal [c1], result[0].replies.without_spam
  315 + assert_equal c2, result[1]
  316 + assert_equal [], result[1].replies.without_spam
  317 + end
  318 +
288 should 'provide author url for authenticated user' do 319 should 'provide author url for authenticated user' do
289 author = Person.new 320 author = Person.new
290 author.expects(:url).returns('http://blabla.net/author') 321 author.expects(:url).returns('http://blabla.net/author')
@@ -389,6 +420,7 @@ class CommentTest &lt; ActiveSupport::TestCase @@ -389,6 +420,7 @@ class CommentTest &lt; ActiveSupport::TestCase
389 end 420 end
390 421
391 should 'be able to select non-spam comments' do 422 should 'be able to select non-spam comments' do
  423 + Comment.destroy_all
392 c1 = fast_create(Comment) 424 c1 = fast_create(Comment)
393 c2 = fast_create(Comment, :spam => false) 425 c2 = fast_create(Comment, :spam => false)
394 c3 = fast_create(Comment, :spam => true) 426 c3 = fast_create(Comment, :spam => true)
@@ -660,6 +692,7 @@ class CommentTest &lt; ActiveSupport::TestCase @@ -660,6 +692,7 @@ class CommentTest &lt; ActiveSupport::TestCase
660 end 692 end
661 693
662 should 'be able to select non-reply comments' do 694 should 'be able to select non-reply comments' do
  695 + Comment.destroy_all
663 c1 = fast_create(Comment) 696 c1 = fast_create(Comment)
664 c2 = fast_create(Comment, :reply_of_id => c1.id) 697 c2 = fast_create(Comment, :reply_of_id => c1.id)
665 c3 = fast_create(Comment, :reply_of_id => c2.id) 698 c3 = fast_create(Comment, :reply_of_id => c2.id)
test/unit/environment_test.rb
@@ -783,6 +783,18 @@ class EnvironmentTest &lt; ActiveSupport::TestCase @@ -783,6 +783,18 @@ class EnvironmentTest &lt; ActiveSupport::TestCase
783 assert role2.valid? 783 assert role2.valid?
784 end 784 end
785 785
  786 + should 'destroy roles when its environment is destroyed' do
  787 + e1 = fast_create(Environment)
  788 + role1 = Role.create!(:name => 'test_role', :environment => e1, :key => 'a_member')
  789 + e2 = fast_create(Environment)
  790 + role2 = Role.create!(:name => 'test_role', :environment => e2, :key => 'a_member')
  791 +
  792 + e2.destroy
  793 +
  794 + assert_nothing_raised {Role.find(role1.id)}
  795 + assert_raise(ActiveRecord::RecordNotFound) {Role.find(role2.id)}
  796 + end
  797 +
786 should 'have a help_message_to_add_enterprise attribute' do 798 should 'have a help_message_to_add_enterprise attribute' do
787 env = Environment.new 799 env = Environment.new
788 800
test/unit/profile_test.rb
@@ -1461,7 +1461,7 @@ class ProfileTest &lt; ActiveSupport::TestCase @@ -1461,7 +1461,7 @@ class ProfileTest &lt; ActiveSupport::TestCase
1461 should 'list events by month' do 1461 should 'list events by month' do
1462 profile = fast_create(Profile) 1462 profile = fast_create(Profile)
1463 1463
1464 - today = Date.today 1464 + today = Date.new(2014, 03, 2)
1465 yesterday_event = Event.new(:name => 'Joao Birthday', :start_date => today - 1.day) 1465 yesterday_event = Event.new(:name => 'Joao Birthday', :start_date => today - 1.day)
1466 today_event = Event.new(:name => 'Ze Birthday', :start_date => today) 1466 today_event = Event.new(:name => 'Ze Birthday', :start_date => today)
1467 tomorrow_event = Event.new(:name => 'Mane Birthday', :start_date => today + 1.day) 1467 tomorrow_event = Event.new(:name => 'Mane Birthday', :start_date => today + 1.day)
vendor/plugins/action_tracker_has_comments/init.rb
@@ -11,5 +11,6 @@ Rails.configuration.to_prepare do @@ -11,5 +11,6 @@ Rails.configuration.to_prepare do
11 type, id = (self.target_type == 'Article' ? ['Article', self.target_id] : [self.class.to_s, self.id]) 11 type, id = (self.target_type == 'Article' ? ['Article', self.target_id] : [self.class.to_s, self.id])
12 "source_type = '#{type}' AND source_id = '#{id}' AND spam IS NOT TRUE AND reply_of_id IS NULL" 12 "source_type = '#{type}' AND source_id = '#{id}' AND spam IS NOT TRUE AND reply_of_id IS NULL"
13 end 13 end
  14 +
14 end 15 end
15 end 16 end