Commit 553f852ef8639e0b62cb928c9fcc3a9fd72435db

Authored by Leandro Santos
Committed by Joenio Costa
1 parent d273adf7

Creating a block to make some images highlighted on environment and enterprises

The user could choose which image It want to see at the moment, each image
may also be associated with a link

(ActionItem1564)
app/controllers/admin/environment_design_controller.rb
... ... @@ -3,7 +3,7 @@ class EnvironmentDesignController < BoxOrganizerController
3 3 protect 'edit_environment_design', :environment
4 4  
5 5 def available_blocks
6   - @available_blocks ||= [ ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, PeopleBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock ]
  6 + @available_blocks ||= [ ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, PeopleBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock ]
7 7 end
8 8  
9 9 end
... ...
app/controllers/my_profile/profile_design_controller.rb
... ... @@ -23,6 +23,7 @@ class ProfileDesignController < BoxOrganizerController
23 23 # blocks exclusive for enterprises
24 24 if profile.enterprise?
25 25 blocks << DisabledEnterpriseMessageBlock
  26 + blocks << HighlightsBlock
26 27 end
27 28  
28 29 # product block exclusive for enterprises in environments that permits it
... ...
app/models/highlights_block.rb 0 → 100644
... ... @@ -0,0 +1,38 @@
  1 +class HighlightsBlock < Block
  2 +
  3 + settings_items :images, :type => Array, :default => []
  4 + settings_items :interval, :type => 'integer', :default => 4
  5 + settings_items :shuffle, :type => 'boolean', :default => false
  6 + settings_items :navigation, :type => 'boolean', :default => false
  7 +
  8 + before_save do |block|
  9 + block.images = block.images.delete_if { |i| i[:image_id].blank? and i[:address].blank? and i[:position].blank? and i[:title].blank? }
  10 + block.images.each do |i|
  11 + i[:image_id] = i[:image_id].to_i
  12 + i[:position] = i[:position].to_i
  13 + begin
  14 + file = UploadedFile.find(i[:image_id])
  15 + i[:image_src] = file.public_filename
  16 + rescue
  17 + i[:image_src] = nil
  18 + end
  19 + end
  20 + end
  21 +
  22 + def self.description
  23 + _('Highlights')
  24 + end
  25 +
  26 + def featured_images
  27 + block_images = images.select{|i| !i[:image_src].nil? }.sort { |x, y| x[:position] <=> y[:position] }
  28 + shuffle ? block_images.shuffle : block_images
  29 + end
  30 +
  31 + def content
  32 + block = self
  33 + lambda do
  34 + render :file => 'blocks/highlights', :locals => { :block => block }
  35 + end
  36 + end
  37 +
  38 +end
... ...
app/views/blocks/highlights.rhtml 0 → 100644
... ... @@ -0,0 +1,29 @@
  1 +<%= block_title(block.title) %>
  2 +<% if !block.featured_images.empty? %>
  3 + <div class='highlights-border'>
  4 + <div class='highlights-container'>
  5 + <% block.featured_images.each do |img| %>
  6 + <a href="<%= img[:address] %>" title="<%= img[:title] %>" class="highlights-image-link">
  7 + <%= content_tag :img, nil, :src => img[:image_src], :alt => img[:title] %>
  8 + <p class="highlights-label"><%= img[:title] %></p>
  9 + </a>
  10 + <% end %>
  11 + </div>
  12 + <% if block.navigation %>
  13 + <div class='highlights-block-pager'>
  14 + </div>
  15 + <% end %>
  16 + </div>
  17 + <p class="highlights-block-footer"></p>
  18 + <script type="text/javascript">
  19 + (function($) {
  20 + var options = {fx: 'fade', fastOnEvent: 1, timeout: <%= block.interval * 1000 %>};
  21 + <% if block.navigation %>
  22 + options.pager = '#block-<%= block.id %> .highlights-block-pager';
  23 + <% end %>
  24 + $('#block-<%= block.id %> .highlights-container').cycle(options);
  25 + })(jQuery);
  26 + </script>
  27 +<% else %>
  28 + <em><%= _('Please, edit this block and choose some images') %></em>
  29 +<% end %>
... ...
app/views/box_organizer/_highlights_block.rhtml 0 → 100644
... ... @@ -0,0 +1,32 @@
  1 +<strong><%= _('Highlights') %></strong>
  2 +<div id='edit-highlights-block'>
  3 +<table id='highlights' class='noborder'>
  4 + <tr><th><%= _('Image') %></th><th><%= _('Address') %></th><th><%= _('Position') %></th><th><%= _('Title') %></th></tr>
  5 + <% for image in @block.images do %>
  6 + <tr>
  7 + <td>
  8 + <%= select_tag 'block[images][][image_id]', content_tag(:option) + option_groups_from_collection_for_select(@block.box.owner.articles.select{|article| article.folder? && article.display_as_gallery? } , :images, :name, :id, :name, image[:image_id].to_i), :style => "width: 100px" %></p>
  9 + </td>
  10 + <td><%= text_field_tag 'block[images][][address]', image[:address], :class => 'highlight-address', :size => 10 %></td>
  11 + <td><%= text_field_tag 'block[images][][position]', image[:position], :class => 'highlight-position', :size => 3 %></td>
  12 + <td><%= text_field_tag 'block[images][][title]', image[:title], :class => 'highlight-title', :size => 10 %></td>
  13 + </tr>
  14 + <% end %>
  15 +</table>
  16 +</div>
  17 +
  18 +<%= link_to_function(_('New highlight'), nil, :class => 'button icon-add with-text') do |page|
  19 + page.insert_html :bottom, 'highlights', content_tag('tr',
  20 + content_tag('td', select_tag('block[images][][image_id]', content_tag(:option) + option_groups_from_collection_for_select(@block.box.owner.articles.select{|article| article.folder? && article.display_as_gallery? } , :images, :name, :id, :name), :style => "width: 100px")) +
  21 + content_tag('td', text_field_tag('block[images][][address]', nil, :class => 'highlight-address', :size => 10)) +
  22 + content_tag('td', text_field_tag('block[images][][position]', nil, :class => 'highlight-position', :size => 3)) +
  23 + content_tag('td', text_field_tag('block[images][][title]', nil, :class => 'highlight-position', :size => 10))
  24 + ) +
  25 + javascript_tag("$('edit-link-list-block').scrollTop = $('edit-link-list-block').scrollHeight")
  26 +end %>
  27 +
  28 +<%= labelled_form_field _('Image transition:'), select('block', 'interval', [[_('No automatic transition'), 0]] + [1, 2, 3, 4, 5, 10, 20, 30, 60].map {|item| [n_('Every 1 second', 'Every %d seconds', item) % item, item]}) %>
  29 +
  30 +<%= labelled_form_field check_box(:block, :shuffle) + _('Show images in random order'), '' %>
  31 +
  32 +<%= labelled_form_field check_box(:block, :navigation) + _('Display navigation buttons'), '' %>
... ...
public/stylesheets/application.css
... ... @@ -3639,3 +3639,56 @@ h1#agenda-title {
3639 3639 width: 500px;
3640 3640 }
3641 3641  
  3642 +/* highlights block stuff */
  3643 +
  3644 +.highlights-block {
  3645 + float: left;
  3646 +}
  3647 +
  3648 +.highlights-block-pager {
  3649 + border: 1px solid #ccc;
  3650 + border-top: 0;
  3651 + display: inline;
  3652 + padding-right: 5px;
  3653 +}
  3654 +
  3655 +.highlights-block-pager a {
  3656 + text-decoration: none;
  3657 + margin-left: 5px;
  3658 +}
  3659 +
  3660 +.highlights-block-pager a.activeSlide:visited,
  3661 +.highlights-block-pager a.activeSlide {
  3662 + color: #000;
  3663 +}
  3664 +
  3665 +.highlights-block a,
  3666 +.highlights-block a:visited {
  3667 + text-decoration: none;
  3668 +}
  3669 +
  3670 +.highlights-image-link {
  3671 + height: 150px;
  3672 + width: 400px;
  3673 + overflow: hidden;
  3674 +}
  3675 +
  3676 +.highlights-label {
  3677 + border: 0;
  3678 + position: absolute;
  3679 + bottom: 0;
  3680 + z-index: 9999;
  3681 + background-color: #000;
  3682 + color: #fff;
  3683 + text-decoration: none;
  3684 + display: block;
  3685 + width: 100%;
  3686 + height: 30px;
  3687 + overflow: hidden;
  3688 + margin: 0;
  3689 + padding: 4px 0;
  3690 +}
  3691 +
  3692 +.highlights-image-link {
  3693 + border: 1px solid #ccc;
  3694 +}
... ...
test/functional/environment_design_controller_test.rb
... ... @@ -6,7 +6,7 @@ class EnvironmentDesignController; def rescue_action(e) raise e end; end
6 6  
7 7 class EnvironmentDesignControllerTest < Test::Unit::TestCase
8 8  
9   - ALL_BLOCKS = [ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, PeopleBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock ]
  9 + ALL_BLOCKS = [ArticleBlock, LoginBlock, EnvironmentStatisticsBlock, RecentDocumentsBlock, EnterprisesBlock, CommunitiesBlock, PeopleBlock, SellersSearchBlock, LinkListBlock, FeedReaderBlock, SlideshowBlock, HighlightsBlock ]
10 10  
11 11 def setup
12 12 @controller = EnvironmentDesignController.new
... ...
test/functional/profile_design_controller_test.rb
... ... @@ -5,6 +5,14 @@ class ProfileDesignController; def rescue_action(e) raise e end; end
5 5  
6 6 class ProfileDesignControllerTest < Test::Unit::TestCase
7 7  
  8 + COMMOM_BLOCKS = [ ArticleBlock, TagsBlock, RecentDocumentsBlock, ProfileInfoBlock, LinkListBlock, MyNetworkBlock, FeedReaderBlock, ProfileImageBlock, LocationBlock, SlideshowBlock]
  9 + PERSON_BLOCKS = COMMOM_BLOCKS + [FriendsBlock, FavoriteEnterprisesBlock, CommunitiesBlock, EnterprisesBlock ]
  10 + PERSON_BLOCKS_WITH_MEMBERS = PERSON_BLOCKS + [MembersBlock]
  11 + PERSON_BLOCKS_WITH_BLOG = PERSON_BLOCKS + [BlogArchivesBlock]
  12 +
  13 + ENTERPRISE_BLOCKS = COMMOM_BLOCKS + [DisabledEnterpriseMessageBlock, HighlightsBlock]
  14 + ENTERPRISE_BLOCKS_WITH_PRODUCTS_ENABLE = ENTERPRISE_BLOCKS + [ProductsBlock]
  15 +
8 16 attr_reader :holder
9 17 def setup
10 18 @controller = ProfileDesignController.new
... ... @@ -324,4 +332,69 @@ class ProfileDesignControllerTest &lt; Test::Unit::TestCase
324 332 assert_tag :tag => 'div', :attributes => {:id => 'access-denied'}
325 333 end
326 334  
  335 + should 'the person blocks are all available' do
  336 + profile = mock
  337 + profile.stubs(:has_members?).returns(false)
  338 + profile.stubs(:person?).returns(true)
  339 + profile.stubs(:enterprise?).returns(false)
  340 + profile.stubs(:has_blog?).returns(false)
  341 + environment = mock
  342 + profile.stubs(:environment).returns(environment)
  343 + environment.stubs(:enabled?).returns(false)
  344 + @controller.stubs(:profile).returns(profile)
  345 + assert_equal PERSON_BLOCKS, @controller.available_blocks
  346 + end
  347 +
  348 + should 'the person with members blocks are all available' do
  349 + profile = mock
  350 + profile.stubs(:has_members?).returns(true)
  351 + profile.stubs(:person?).returns(true)
  352 + profile.stubs(:enterprise?).returns(false)
  353 + profile.stubs(:has_blog?).returns(false)
  354 + environment = mock
  355 + profile.stubs(:environment).returns(environment)
  356 + environment.stubs(:enabled?).returns(false)
  357 + @controller.stubs(:profile).returns(profile)
  358 + assert_equal [], @controller.available_blocks - PERSON_BLOCKS_WITH_MEMBERS
  359 + end
  360 +
  361 + should 'the person with blog blocks are all available' do
  362 + profile = mock
  363 + profile.stubs(:has_members?).returns(false)
  364 + profile.stubs(:person?).returns(true)
  365 + profile.stubs(:enterprise?).returns(false)
  366 + profile.stubs(:has_blog?).returns(true)
  367 + environment = mock
  368 + profile.stubs(:environment).returns(environment)
  369 + environment.stubs(:enabled?).returns(false)
  370 + @controller.stubs(:profile).returns(profile)
  371 + assert_equal [], @controller.available_blocks - PERSON_BLOCKS_WITH_BLOG
  372 + end
  373 +
  374 + should 'the enterprise blocks are all available' do
  375 + profile = mock
  376 + profile.stubs(:has_members?).returns(false)
  377 + profile.stubs(:person?).returns(false)
  378 + profile.stubs(:enterprise?).returns(true)
  379 + profile.stubs(:has_blog?).returns(false)
  380 + environment = mock
  381 + profile.stubs(:environment).returns(environment)
  382 + environment.stubs(:enabled?).returns(true)
  383 + @controller.stubs(:profile).returns(profile)
  384 + assert_equal [], @controller.available_blocks - ENTERPRISE_BLOCKS
  385 + end
  386 +
  387 + should 'the enterprise with products for enterprise enable blocks are all available' do
  388 + profile = mock
  389 + profile.stubs(:has_members?).returns(false)
  390 + profile.stubs(:person?).returns(false)
  391 + profile.stubs(:enterprise?).returns(true)
  392 + profile.stubs(:has_blog?).returns(false)
  393 + environment = mock
  394 + profile.stubs(:environment).returns(environment)
  395 + environment.stubs(:enabled?).returns(false)
  396 + @controller.stubs(:profile).returns(profile)
  397 + assert_equal [], @controller.available_blocks - ENTERPRISE_BLOCKS_WITH_PRODUCTS_ENABLE
  398 + end
  399 +
327 400 end
... ...
test/unit/highlights_block_test.rb 0 → 100644
... ... @@ -0,0 +1,130 @@
  1 +require File.dirname(__FILE__) + '/../test_helper'
  2 +
  3 +class HighlightsBlockTest < ActiveSupport::TestCase
  4 +
  5 + should 'default describe' do
  6 + assert_not_equal Block.description, HighlightsBlock.description
  7 + end
  8 +
  9 + should 'have field images' do
  10 + h = HighlightsBlock.new
  11 + assert_respond_to h, :images
  12 + end
  13 +
  14 + should 'have field interval' do
  15 + h = HighlightsBlock.new
  16 + assert_respond_to h, :interval
  17 + end
  18 +
  19 + should 'have field shuffle' do
  20 + h = HighlightsBlock.new
  21 + assert_respond_to h, :shuffle
  22 + end
  23 +
  24 + should 'have field navigation' do
  25 + h = HighlightsBlock.new
  26 + assert_respond_to h, :navigation
  27 + end
  28 +
  29 + should 'default value of images' do
  30 + h = HighlightsBlock.new
  31 + assert_equal [], h.images
  32 + end
  33 +
  34 + should 'default interval between transitions is 4 seconds' do
  35 + h = HighlightsBlock.new
  36 + assert_equal 4, h.interval
  37 + end
  38 +
  39 + should 'default value of shuffle' do
  40 + h = HighlightsBlock.new
  41 + assert_equal false, h.shuffle
  42 + end
  43 +
  44 + should 'default value of navigation' do
  45 + h = HighlightsBlock.new
  46 + assert_equal false, h.navigation
  47 + end
  48 +
  49 + should 'is editable' do
  50 + h = HighlightsBlock.new
  51 + assert h.editable?
  52 + end
  53 +
  54 + should 'remove images with blank fields' do
  55 + h = HighlightsBlock.new(:images => [{:image_id => 1, :address => '/address', :position => 1, :title => 'address'}, {:image_id => '', :address => '', :position => '', :title => ''}])
  56 + h.save!
  57 + assert_equal [{:image_id => 1, :address => '/address', :position => 1, :title => 'address', :image_src => nil}], h.images
  58 + end
  59 +
  60 + should 'be able to update display setting' do
  61 + user = create_user('testinguser').person
  62 + box = fast_create(Box, :owner_id => user.id)
  63 + block = HighlightsBlock.create!(:display => 'never', :box => box)
  64 + assert block.update_attributes!(:display => 'always')
  65 + block.reload
  66 + assert_equal 'always', block.display
  67 + end
  68 +
  69 + should 'display highlights block' do
  70 + block = HighlightsBlock.new
  71 + self.expects(:render).with(:file => 'blocks/highlights', :locals => { :block => block})
  72 +
  73 + instance_eval(& block.content)
  74 + end
  75 +
  76 + should 'not list non existent image' do
  77 + file = mock()
  78 + UploadedFile.expects(:find).with(1).returns(file)
  79 + file.expects(:public_filename).returns('address')
  80 + block = HighlightsBlock.new(:images => [{:image_id => 1, :address => '/address', :position => 1, :title => 'address'}, {:image_id => '', :address => 'some', :position => '2', :title => 'Some'}])
  81 + block.save!
  82 + block.reload
  83 + assert_equal 2, block.images.count
  84 + assert_equal [{:image_id => 1, :address => '/address', :position => 1, :title => 'address', :image_src => 'address'}], block.featured_images
  85 + end
  86 +
  87 + should 'list images in order' do
  88 + f1 = mock()
  89 + f1.expects(:public_filename).returns('address')
  90 + UploadedFile.expects(:find).with(1).returns(f1)
  91 + f2 = mock()
  92 + f2.expects(:public_filename).returns('address')
  93 + UploadedFile.expects(:find).with(2).returns(f2)
  94 + f3 = mock()
  95 + f3.expects(:public_filename).returns('address')
  96 + UploadedFile.expects(:find).with(3).returns(f3)
  97 + block = HighlightsBlock.new
  98 + i1 = {:image_id => 1, :address => '/address', :position => 3, :title => 'address'}
  99 + i2 = {:image_id => 2, :address => '/address', :position => 1, :title => 'address'}
  100 + i3 = {:image_id => 3, :address => '/address', :position => 2, :title => 'address'}
  101 + block.images = [i1,i2,i3]
  102 + block.save!
  103 + block.reload
  104 + assert_equal [i1,i2,i3], block.images
  105 + assert_equal [i2,i3,i1], block.featured_images
  106 + end
  107 +
  108 + should 'list images randomically' do
  109 + f1 = mock()
  110 + f1.expects(:public_filename).returns('address')
  111 + UploadedFile.expects(:find).with(1).returns(f1)
  112 + f2 = mock()
  113 + f2.expects(:public_filename).returns('address')
  114 + UploadedFile.expects(:find).with(2).returns(f2)
  115 + f3 = mock()
  116 + f3.expects(:public_filename).returns('address')
  117 + UploadedFile.expects(:find).with(3).returns(f3)
  118 + block = HighlightsBlock.new
  119 + i1 = {:image_id => 1, :address => '/address', :position => 3, :title => 'address'}
  120 + i2 = {:image_id => 2, :address => '/address', :position => 1, :title => 'address'}
  121 + i3 = {:image_id => 3, :address => '/address', :position => 2, :title => 'address'}
  122 + block.images = [i1,i2,i3]
  123 + block.shuffle = true
  124 + block.save!
  125 + block.reload
  126 + assert_equal [i1,i2,i3], block.images
  127 + assert_not_equal [i2,i3,i1], block.featured_images
  128 + end
  129 +
  130 +end
... ...