Commit ffbf0914d4ca1302cbc00175b4b73b84d9ddb144
Exists in
master
and in
29 other branches
Merge branch 'AI2943_container_block_fixes' into 'stable'
Ai2943 Container Block Fixes Fix broken edition for container block with the new css for sideboxes view.
Showing
16 changed files
with
137 additions
and
144 deletions
Show diff stats
app/controllers/box_organizer_controller.rb
... | ... | @@ -70,7 +70,7 @@ class BoxOrganizerController < ApplicationController |
70 | 70 | else |
71 | 71 | @center_block_types = (Box.acceptable_center_blocks & available_blocks) + plugins.dispatch(:extra_blocks, :type => boxes_holder.class, :position => 1) |
72 | 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 | 74 | render :action => 'add_block', :layout => false |
75 | 75 | end |
76 | 76 | end | ... | ... |
app/helpers/boxes_helper.rb
... | ... | @@ -39,7 +39,7 @@ module BoxesHelper |
39 | 39 | end |
40 | 40 | |
41 | 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 | 43 | content = boxes.reverse.map { |item| display_box(item, main_content) }.join("\n") |
44 | 44 | content = main_content if (content.blank?) |
45 | 45 | ... | ... |
app/models/box.rb
plugins/container_block/lib/container_block_plugin.rb
plugins/container_block/lib/container_block_plugin/container_block.rb
... | ... | @@ -7,6 +7,16 @@ class ContainerBlockPlugin::ContainerBlock < Block |
7 | 7 | settings_items :container_box_id, :type => Integer, :default => nil |
8 | 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 | 20 | def self.description |
11 | 21 | _('Container') |
12 | 22 | end |
... | ... | @@ -15,6 +25,10 @@ class ContainerBlockPlugin::ContainerBlock < Block |
15 | 25 | _('This block acts as a container for another blocks') |
16 | 26 | end |
17 | 27 | |
28 | + def cacheable? | |
29 | + false | |
30 | + end | |
31 | + | |
18 | 32 | def layout_template |
19 | 33 | nil |
20 | 34 | end |
... | ... | @@ -24,8 +38,9 @@ class ContainerBlockPlugin::ContainerBlock < Block |
24 | 38 | end |
25 | 39 | |
26 | 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 | 44 | save! |
30 | 45 | end |
31 | 46 | ... | ... |
... | ... | @@ -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 | 7 | #content .boxes .container-block-plugin_container-block .container_block_child, .container-block-plugin_container-block .block-outer { |
2 | 8 | display: inline-block; |
3 | 9 | vertical-align: top; |
... | ... | @@ -17,14 +23,10 @@ |
17 | 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 | 26 | #content .boxes .container-block-plugin_container-block .block .ui-resizable-handle { |
25 | 27 | width: 10px; |
26 | 28 | height: 28px; |
27 | - z-index: 0; | |
29 | + z-index: 1000; | |
28 | 30 | } |
29 | 31 | |
30 | 32 | #content .boxes .container-block-plugin_container-block .block .ui-resizable-e { |
... | ... | @@ -37,6 +39,21 @@ |
37 | 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 | 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 < ActionController::TestCase |
31 | 31 | assert_tag :div, :attributes => { :class => 'block container-block-plugin_container-block' } |
32 | 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 | 41 | should 'display container children' do |
35 | 42 | c1 = RawHTMLBlock.create!(:box => @block.container_box, :html => 'child1 content') |
36 | 43 | c2 = RawHTMLBlock.create!(:box => @block.container_box, :html => 'child2 content') | ... | ... |
plugins/container_block/test/unit/block_test.rb
... | ... | @@ -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 < ActiveSupport::TestCase |
20 | 20 | assert @block.container_box_id |
21 | 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 | 28 | should 'return created box' do |
24 | 29 | @block.save! |
25 | 30 | assert @block.container_box |
... | ... | @@ -89,4 +94,27 @@ class ContainerBlockPlugin::ContainerBlockTest < ActiveSupport::TestCase |
89 | 94 | end |
90 | 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 | 120 | end | ... | ... |
plugins/container_block/test/unit/environment_test.rb
... | ... | @@ -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 | -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 | 1 | <% edit_mode = @controller.send(:boxes_editor?) && @controller.send(:uses_design_blocks?) %> |
2 | 2 | <% box_decorator = edit_mode ? self : BoxesHelper::DontMoveBlocks %> |
3 | 3 | |
4 | +<%= block_title(block.title) %> | |
4 | 5 | |
5 | 6 | <div class="box" id="box-<%= block.container_box.id %>"> |
6 | 7 | <%= display_box_content(block.container_box, nil) %> |
... | ... | @@ -15,8 +16,18 @@ |
15 | 16 | </style> |
16 | 17 | |
17 | 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 | 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 | 32 | :with => "containerChildrenWidth(#{block.id}, #{block.container_box.id})", |
22 | 33 | :html => {:class => "button icon-save container_block_save", :id => "container_block_save_#{block.id}", :title => _('Save') }, |
... | ... | @@ -24,37 +35,4 @@ |
24 | 35 | :loaded => "close_loading();", |
25 | 36 | :complete => "display_notice(request.responseText);"%> |
26 | 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 | 38 | <% end %> | ... | ... |
public/stylesheets/application.css
... | ... | @@ -1735,8 +1735,8 @@ a.button.disabled, input.disabled { |
1735 | 1735 | display: none; |
1736 | 1736 | } |
1737 | 1737 | |
1738 | -#box-organizer .block:focus .button-bar, | |
1739 | -#box-organizer .block:hover .button-bar { | |
1738 | +#box-organizer .block-outer:focus .button-bar, | |
1739 | +#box-organizer .block-outer:hover .button-bar { | |
1740 | 1740 | display: block; |
1741 | 1741 | } |
1742 | 1742 | ... | ... |
test/unit/box_test.rb
... | ... | @@ -140,4 +140,11 @@ class BoxTest < ActiveSupport::TestCase |
140 | 140 | assert !blocks.include?('box-test_plugin-block') |
141 | 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 | 150 | end | ... | ... |
test/unit/boxes_helper_test.rb
... | ... | @@ -13,7 +13,8 @@ class BoxesHelperTest < ActiveSupport::TestCase |
13 | 13 | |
14 | 14 | should 'include profile-specific header' do |
15 | 15 | holder = mock |
16 | - holder.stubs(:boxes).returns([]) | |
16 | + holder.stubs(:boxes).returns(boxes = []) | |
17 | + boxes.stubs(:with_position).returns([]) | |
17 | 18 | holder.stubs(:boxes_limit).returns(0) |
18 | 19 | holder.stubs(:custom_header_expanded).returns('my custom header') |
19 | 20 | @controller.stubs(:boxes_holder).returns(holder) |
... | ... | @@ -23,7 +24,8 @@ class BoxesHelperTest < ActiveSupport::TestCase |
23 | 24 | |
24 | 25 | should 'include profile-specific footer' do |
25 | 26 | holder = mock |
26 | - holder.stubs(:boxes).returns([]) | |
27 | + holder.stubs(:boxes).returns(boxes = []) | |
28 | + boxes.stubs(:with_position).returns([]) | |
27 | 29 | holder.stubs(:boxes_limit).returns(0) |
28 | 30 | holder.stubs(:custom_footer_expanded).returns('my custom footer') |
29 | 31 | @controller.stubs(:boxes_holder).returns(holder) | ... | ... |