Commit 7eefa439e719d9e7f7d22cb26b42563253b6985e
Exists in
master
and in
21 other branches
Merge branch 'fixed-block' into 'master'
Fixed block Make a specific block fixed on a position. Only the environment admin can move and specify this option for the block https://gitlab.com/noosfero/noosfero/issues/26 See merge request !380
Showing
6 changed files
with
102 additions
and
31 deletions
Show diff stats
app/controllers/my_profile/profile_design_controller.rb
| @@ -3,7 +3,16 @@ class ProfileDesignController < BoxOrganizerController | @@ -3,7 +3,16 @@ class ProfileDesignController < BoxOrganizerController | ||
| 3 | needs_profile | 3 | needs_profile |
| 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] | ||
| 8 | + | ||
| 9 | + def protect_fixed_block | ||
| 10 | + block = boxes_holder.blocks.find(params[:id].gsub(/^block-/, '')) | ||
| 11 | + if block.fixed && !current_person.is_admin? | ||
| 12 | + render_access_denied | ||
| 13 | + end | ||
| 14 | + end | ||
| 15 | + | ||
| 7 | def available_blocks | 16 | def available_blocks |
| 8 | blocks = [ ArticleBlock, TagsBlock, RecentDocumentsBlock, ProfileInfoBlock, LinkListBlock, MyNetworkBlock, FeedReaderBlock, ProfileImageBlock, LocationBlock, SlideshowBlock, ProfileSearchBlock, HighlightsBlock ] | 17 | blocks = [ ArticleBlock, TagsBlock, RecentDocumentsBlock, ProfileInfoBlock, LinkListBlock, MyNetworkBlock, FeedReaderBlock, ProfileImageBlock, LocationBlock, SlideshowBlock, ProfileSearchBlock, HighlightsBlock ] |
| 9 | 18 |
app/helpers/boxes_helper.rb
| @@ -170,49 +170,54 @@ module BoxesHelper | @@ -170,49 +170,54 @@ module BoxesHelper | ||
| 170 | else | 170 | else |
| 171 | "before-block-#{block.id}" | 171 | "before-block-#{block.id}" |
| 172 | end | 172 | end |
| 173 | - | ||
| 174 | - content_tag('div', ' ', :id => id, :class => 'block-target' ) + drop_receiving_element(id, :url => { :action => 'move_block', :target => id }, :accept => box.acceptable_blocks, :hoverclass => 'block-target-hover') | 173 | + if block.nil? or modifiable?(block) |
| 174 | + content_tag('div', ' ', :id => id, :class => 'block-target' ) + drop_receiving_element(id, :url => { :action => 'move_block', :target => id }, :accept => box.acceptable_blocks, :hoverclass => 'block-target-hover') | ||
| 175 | + else | ||
| 176 | + "" | ||
| 177 | + end | ||
| 175 | end | 178 | end |
| 176 | 179 | ||
| 177 | # makes the given block draggable so it can be moved away. | 180 | # makes the given block draggable so it can be moved away. |
| 178 | def block_handle(block) | 181 | def block_handle(block) |
| 179 | - draggable_element("block-#{block.id}", :revert => true) | 182 | + modifiable?(block) ? draggable_element("block-#{block.id}", :revert => true) : "" |
| 180 | end | 183 | end |
| 181 | 184 | ||
| 182 | def block_edit_buttons(block) | 185 | def block_edit_buttons(block) |
| 183 | buttons = [] | 186 | buttons = [] |
| 184 | nowhere = 'javascript: return false;' | 187 | nowhere = 'javascript: return false;' |
| 185 | 188 | ||
| 186 | - if block.first? | ||
| 187 | - buttons << icon_button('up-disabled', _("Can't move up anymore."), nowhere) | ||
| 188 | - else | ||
| 189 | - buttons << icon_button('up', _('Move block up'), { :action => 'move_block_up', :id => block.id }, { :method => 'post' }) | ||
| 190 | - end | 189 | + if modifiable?(block) |
| 190 | + if block.first? | ||
| 191 | + buttons << icon_button('up-disabled', _("Can't move up anymore."), nowhere) | ||
| 192 | + else | ||
| 193 | + buttons << icon_button('up', _('Move block up'), { :action => 'move_block_up', :id => block.id }, { :method => 'post' }) | ||
| 194 | + end | ||
| 191 | 195 | ||
| 192 | - if block.last? | ||
| 193 | - buttons << icon_button('down-disabled', _("Can't move down anymore."), nowhere) | ||
| 194 | - else | ||
| 195 | - buttons << icon_button(:down, _('Move block down'), { :action => 'move_block_down' ,:id => block.id }, { :method => 'post'}) | ||
| 196 | - end | 196 | + if block.last? |
| 197 | + buttons << icon_button('down-disabled', _("Can't move down anymore."), nowhere) | ||
| 198 | + else | ||
| 199 | + buttons << icon_button(:down, _('Move block down'), { :action => 'move_block_down' ,:id => block.id }, { :method => 'post'}) | ||
| 200 | + end | ||
| 197 | 201 | ||
| 198 | - holder = block.owner | ||
| 199 | - # move to opposite side | ||
| 200 | - # FIXME too much hardcoded stuff | ||
| 201 | - if holder.layout_template == 'default' | ||
| 202 | - if block.box.position == 2 # area 2, left side => move to right side | ||
| 203 | - buttons << icon_button('right', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[2].id.to_s, :id => block.id }, :method => 'post' ) | ||
| 204 | - elsif block.box.position == 3 # area 3, right side => move to left side | ||
| 205 | - 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' ) | 202 | + holder = block.owner |
| 203 | + # move to opposite side | ||
| 204 | + # FIXME too much hardcoded stuff | ||
| 205 | + if holder.layout_template == 'default' | ||
| 206 | + if block.box.position == 2 # area 2, left side => move to right side | ||
| 207 | + buttons << icon_button('right', _('Move to the opposite side'), { :action => 'move_block', :target => 'end-of-box-' + holder.boxes[2].id.to_s, :id => block.id }, :method => 'post' ) | ||
| 208 | + elsif block.box.position == 3 # area 3, right side => move to left side | ||
| 209 | + 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' ) | ||
| 210 | + end | ||
| 206 | end | 211 | end |
| 207 | - end | ||
| 208 | 212 | ||
| 209 | - if block.editable? | ||
| 210 | - buttons << colorbox_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id }) | ||
| 211 | - end | 213 | + if block.editable? |
| 214 | + buttons << colorbox_icon_button(:edit, _('Edit'), { :action => 'edit', :id => block.id }) | ||
| 215 | + end | ||
| 212 | 216 | ||
| 213 | - if !block.main? | ||
| 214 | - buttons << icon_button(:delete, _('Remove block'), { :action => 'remove', :id => block.id }, { :method => 'post', :confirm => _('Are you sure you want to remove this block?')}) | ||
| 215 | - buttons << icon_button(:clone, _('Clone'), { :action => 'clone_block', :id => block.id }, { :method => 'post' }) | 217 | + if !block.main? |
| 218 | + buttons << icon_button(:delete, _('Remove block'), { :action => 'remove', :id => block.id }, { :method => 'post', :confirm => _('Are you sure you want to remove this block?')}) | ||
| 219 | + buttons << icon_button(:clone, _('Clone'), { :action => 'clone_block', :id => block.id }, { :method => 'post' }) | ||
| 220 | + end | ||
| 216 | end | 221 | end |
| 217 | 222 | ||
| 218 | if block.respond_to?(:help) | 223 | if block.respond_to?(:help) |
| @@ -248,5 +253,7 @@ module BoxesHelper | @@ -248,5 +253,7 @@ module BoxesHelper | ||
| 248 | classes | 253 | classes |
| 249 | end | 254 | end |
| 250 | 255 | ||
| 251 | - | 256 | + def modifiable?(block) |
| 257 | + return !block.fixed || environment.admins.include?(user) | ||
| 258 | + end | ||
| 252 | end | 259 | end |
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 | 3 | + attr_accessible :title, :display, :limit, :box_id, :posts_per_page, :visualization_format, :language, :display_user, :box, :fixed |
| 4 | 4 | ||
| 5 | # to be able to generate HTML | 5 | # to be able to generate HTML |
| 6 | include ActionView::Helpers::UrlHelper | 6 | include ActionView::Helpers::UrlHelper |
| @@ -110,6 +110,9 @@ class Block < ActiveRecord::Base | @@ -110,6 +110,9 @@ class Block < ActiveRecord::Base | ||
| 110 | # * <tt>'all'</tt>: the block is always displayed | 110 | # * <tt>'all'</tt>: the block is always displayed |
| 111 | settings_items :language, :type => :string, :default => 'all' | 111 | settings_items :language, :type => :string, :default => 'all' |
| 112 | 112 | ||
| 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 | + | ||
| 113 | # returns the description of the block, used when the user sees a list of | 116 | # returns the description of the block, used when the user sees a list of |
| 114 | # blocks to choose one to include in the design. | 117 | # blocks to choose one to include in the design. |
| 115 | # | 118 | # |
app/views/box_organizer/edit.html.erb
| @@ -5,6 +5,12 @@ | @@ -5,6 +5,12 @@ | ||
| 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 | + | ||
| 8 | <%= render :partial => partial_for_class(@block.class) %> | 14 | <%= render :partial => partial_for_class(@block.class) %> |
| 9 | 15 | ||
| 10 | <div class="display"> | 16 | <div class="display"> |
test/functional/profile_design_controller_test.rb
| @@ -737,4 +737,22 @@ class ProfileDesignControllerTest < ActionController::TestCase | @@ -737,4 +737,22 @@ class ProfileDesignControllerTest < ActionController::TestCase | ||
| 737 | end | 737 | end |
| 738 | end | 738 | end |
| 739 | 739 | ||
| 740 | + test 'should forbid POST to save for fixed blocks' do | ||
| 741 | + block = profile.blocks.last | ||
| 742 | + block.fixed = true | ||
| 743 | + block.save! | ||
| 744 | + | ||
| 745 | + post :save, id: block.id, profile: profile.identifier | ||
| 746 | + assert_response :forbidden | ||
| 747 | + end | ||
| 748 | + | ||
| 749 | + test 'should forbid POST to move_block for fixed blocks' do | ||
| 750 | + block = profile.blocks.last | ||
| 751 | + block.fixed = true | ||
| 752 | + block.save! | ||
| 753 | + | ||
| 754 | + post :move_block, id: block.id, profile: profile.identifier, target: "end-of-box-#{@box3.id}" | ||
| 755 | + assert_response :forbidden | ||
| 756 | + end | ||
| 757 | + | ||
| 740 | end | 758 | end |
test/unit/boxes_helper_test.rb
| 1 | require File.dirname(__FILE__) + '/../test_helper' | 1 | require File.dirname(__FILE__) + '/../test_helper' |
| 2 | +require File.dirname(__FILE__) + '/../../app/helpers/boxes_helper' | ||
| 2 | 3 | ||
| 3 | class BoxesHelperTest < ActionView::TestCase | 4 | class BoxesHelperTest < ActionView::TestCase |
| 4 | 5 | ||
| @@ -119,4 +120,31 @@ class BoxesHelperTest < ActionView::TestCase | @@ -119,4 +120,31 @@ class BoxesHelperTest < ActionView::TestCase | ||
| 119 | display_box_content(box, '') | 120 | display_box_content(box, '') |
| 120 | end | 121 | end |
| 121 | 122 | ||
| 123 | + should 'not show move options on block when block is fixed' do | ||
| 124 | + p = create_user_with_blocks | ||
| 125 | + | ||
| 126 | + b = p.blocks.select{|bk| !bk.kind_of?(MainBlock) }[0] | ||
| 127 | + b.fixed = true | ||
| 128 | + b.save! | ||
| 129 | + | ||
| 130 | + stubs(:environment).returns(p.environment) | ||
| 131 | + stubs(:user).returns(p) | ||
| 132 | + | ||
| 133 | + assert_equal false, modifiable?(b) | ||
| 134 | + end | ||
| 135 | + | ||
| 136 | + should 'show move options on block when block is fixed and user is admin' do | ||
| 137 | + p = create_user_with_blocks | ||
| 138 | + | ||
| 139 | + b = p.blocks.select{|bk| !bk.kind_of?(MainBlock) }[0] | ||
| 140 | + b.fixed = true | ||
| 141 | + b.save! | ||
| 142 | + | ||
| 143 | + p.environment.add_admin(p) | ||
| 144 | + | ||
| 145 | + stubs(:environment).returns(p.environment) | ||
| 146 | + stubs(:user).returns(p) | ||
| 147 | + | ||
| 148 | + assert_equal true, modifiable?(b) | ||
| 149 | + end | ||
| 122 | end | 150 | end |